Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/editor/preview/Preview.java9
-rw-r--r--plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElement.java6
-rw-r--r--plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElementFactory.java27
-rw-r--r--plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElement.java8
-rw-r--r--plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElementFactory.java22
-rw-r--r--plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericPropertyModelElementFactory.java22
-rw-r--r--plugins/customization/org.eclipse.papyrus.customization/src/org/eclipse/papyrus/customization/modelelement/CustomizationModelElementFactory.java8
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSModelElementFactory.java13
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSPreferencesModelElementFactory.java8
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElement.java9
-rw-r--r--plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElementFactory.java22
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/AppearanceModelElementFactory.java4
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElementFactory.java12
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElementFactory.java24
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/NotationModelElementFactory.java42
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulerAndGridModelElement.java11
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulersAndGridModelElementFactory.java34
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableFactory.java19
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/META-INF/MANIFEST.MF3
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingInvocationHandler.java174
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservable.java348
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableCollection.java131
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableList.java205
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableSet.java128
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableValue.java140
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/IDelegatingObservable.java53
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/MultipleObservableValue.java14
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/ReferenceCountedObservable.java372
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java19
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/BehaviorDisplayHelper.java22
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/GateModelElementFactory.java20
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/InteractionOperandModelElementFactory.java23
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/LinkRouteModelElementFactory.java11
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/MessageStyleElementFactory.java32
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/PreferencesModelElementFactory.java23
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CommentModelElementFactory.java12
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CustomImageModelElementFactory.java21
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/MemberEndModelElement.java5
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/ProfileDefinitionModelElementFactory.java20
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceFactory.java23
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceModelElement.java4
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationFactory.java24
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationModelElement.java10
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeModelElementFactory.java13
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLEditorFactory.java21
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLModelElementFactory.java11
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationFactory.java19
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationModelElement.java3
-rw-r--r--plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/widgets/StereotypeApplication.java32
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/AbstractUMLAggregatedObservableValue.java8
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/MultiplicityObservableValue.java5
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/NavigationObservableValue.java5
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/OwnerObservableValue.java5
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/PapyrusObservableValue.java20
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractEMFModelElementFactory.java41
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElement.java98
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElementFactory.java40
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AnnotationModelElementFactory.java18
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/CompositeModelElement.java70
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSource.java57
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceChangedEvent.java32
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceFactory.java11
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/EMFModelElementFactory.java10
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/IDataSourceListener.java30
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/PreferencesModelElementFactory.java21
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/DefaultDisplayEngine.java95
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/TabModel.java165
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/widgets/AbstractPropertyEditor.java59
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSection.java18
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSectionDescriptor.java34
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTTabDescriptor.java39
71 files changed, 2800 insertions, 317 deletions
diff --git a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/editor/preview/Preview.java b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/editor/preview/Preview.java
index 176eb5e4ced..50befdfc36a 100644
--- a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/editor/preview/Preview.java
+++ b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/editor/preview/Preview.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
@@ -9,6 +9,8 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - Use URIs to support non-URL-compatible storage (CDO)
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.customization.properties.editor.preview;
@@ -327,6 +329,11 @@ public class Preview extends ViewPart implements ISelectionChangedListener, IPar
setPreviewError(null);
+ if(displayEngine != null) {
+ // Dispose of the old engine before employing a new one
+ displayEngine.dispose();
+ }
+
displayEngine = new DefaultDisplayEngine();
Map<Tab, Composite> tabs = new HashMap<Tab, Composite>();
diff --git a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElement.java b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElement.java
index 08963971b18..63d01c00974 100644
--- a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElement.java
+++ b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElement.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.customization.properties.modelelement;
@@ -65,7 +67,7 @@ import org.eclipse.papyrus.views.properties.ui.PropertyEditor;
*/
public class CustomizationModelElement extends AbstractModelElement {
- private EMFModelElement delegate;
+ protected EMFModelElement delegate;
private static Map<EClassifier, IStaticContentProvider> providers;
diff --git a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElementFactory.java b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElementFactory.java
index 63c2495ac89..9a3d00d99d1 100644
--- a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElementFactory.java
+++ b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/CustomizationModelElementFactory.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,23 +8,40 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.customization.properties.modelelement;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractEMFModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
import org.eclipse.papyrus.views.properties.modelelement.EMFModelElement;
import org.eclipse.papyrus.views.properties.modelelement.EMFModelElementFactory;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
/**
* A Factory for build {@link CustomizationModelElement}s
*
* @author Camille Letavernier
*/
-public class CustomizationModelElementFactory extends EMFModelElementFactory {
+public class CustomizationModelElementFactory extends AbstractModelElementFactory<CustomizationModelElement> {
+ private static final EMFModelElementFactory emfFactory = new EMFModelElementFactory();
+
+ @Override
+ protected CustomizationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
+ return new CustomizationModelElement((EMFModelElement)emfFactory.createFromSource(sourceElement, context));
+ }
+
@Override
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
- return new CustomizationModelElement((EMFModelElement)super.createFromSource(sourceElement, context));
+ protected void updateModelElement(CustomizationModelElement modelElement, Object newSourceElement) {
+ EObject eObject = EMFHelper.getEObject(newSourceElement);
+ if(eObject == null) {
+ throw new IllegalArgumentException("Cannot resolve EObject selection: " + newSourceElement);
+ }
+
+ AbstractEMFModelElementFactory.updateEMFModelElement(modelElement.delegate, eObject);
}
}
diff --git a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElement.java b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElement.java
index b5e124cca1e..06f1e8ebbde 100644
--- a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElement.java
+++ b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElement.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.customization.properties.modelelement;
@@ -63,9 +65,9 @@ import org.eclipse.papyrus.views.properties.ui.WidgetAttribute;
*/
public class GenericAttributeModelElement extends AbstractModelElement {
- private EObject source;
+ protected EObject source;
- private EditingDomain domain;
+ protected EditingDomain domain;
private EStructuralFeature createIn;
diff --git a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElementFactory.java b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElementFactory.java
index 6dcb389a966..063125a3c1f 100644
--- a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElementFactory.java
+++ b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericAttributeModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.customization.properties.modelelement;
@@ -19,21 +21,22 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.customization.properties.Activator;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
import org.eclipse.papyrus.views.properties.ui.UiFactory;
import org.eclipse.papyrus.views.properties.ui.UiPackage;
+import org.eclipse.papyrus.views.properties.ui.WidgetAttribute;
/**
* A ModelElementFactory for handling {@link WidgetAttribute} properties
*
* @author Camille Letavernier
*/
-public class GenericAttributeModelElementFactory implements ModelElementFactory {
+public class GenericAttributeModelElementFactory extends AbstractModelElementFactory<GenericAttributeModelElement> {
//Source : Group
//context : Custom:Attribute:Group
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected GenericAttributeModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the source element to an EObject"); //$NON-NLS-1$
@@ -53,4 +56,13 @@ public class GenericAttributeModelElementFactory implements ModelElementFactory
// throw new UnsupportedOperationException();
// }
+ @Override
+ protected void updateModelElement(GenericAttributeModelElement modelElement, Object newSourceElement) {
+ EObject eObject = EMFHelper.getEObject(newSourceElement);
+ if(eObject == null) {
+ throw new IllegalArgumentException("Cannot resolve EObject selection: " + newSourceElement);
+ }
+ modelElement.source = eObject;
+ modelElement.domain = EMFHelper.resolveEditingDomain(eObject);
+ }
}
diff --git a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericPropertyModelElementFactory.java b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericPropertyModelElementFactory.java
index 15df8d144f7..4745a06dc1c 100644
--- a/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericPropertyModelElementFactory.java
+++ b/plugins/customization/org.eclipse.papyrus.customization.properties/src/org/eclipse/papyrus/customization/properties/modelelement/GenericPropertyModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.customization.properties.modelelement;
@@ -17,23 +19,24 @@ import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.customization.properties.Activator;
+import org.eclipse.papyrus.infra.constraints.ConfigProperty;
import org.eclipse.papyrus.infra.constraints.ConstraintsFactory;
import org.eclipse.papyrus.infra.constraints.ConstraintsPackage;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
/**
* A ModelElementFactory for handling {@link ConfigProperty} properties
*
* @author Camille Letavernier
*/
-public class GenericPropertyModelElementFactory implements ModelElementFactory {
+public class GenericPropertyModelElementFactory extends AbstractModelElementFactory<GenericAttributeModelElement> {
//Source : Group
//context : Custom:Attribute:Group
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected GenericAttributeModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
@@ -54,4 +57,13 @@ public class GenericPropertyModelElementFactory implements ModelElementFactory {
// throw new UnsupportedOperationException();
// }
+ @Override
+ protected void updateModelElement(GenericAttributeModelElement modelElement, Object newSourceElement) {
+ EObject eObject = EMFHelper.getEObject(newSourceElement);
+ if(eObject == null) {
+ throw new IllegalArgumentException("Cannot resolve EObject selection: " + newSourceElement);
+ }
+ modelElement.source = eObject;
+ modelElement.domain = EMFHelper.resolveEditingDomain(eObject);
+ }
}
diff --git a/plugins/customization/org.eclipse.papyrus.customization/src/org/eclipse/papyrus/customization/modelelement/CustomizationModelElementFactory.java b/plugins/customization/org.eclipse.papyrus.customization/src/org/eclipse/papyrus/customization/modelelement/CustomizationModelElementFactory.java
index 9a52966638f..5f98a4a45ed 100644
--- a/plugins/customization/org.eclipse.papyrus.customization/src/org/eclipse/papyrus/customization/modelelement/CustomizationModelElementFactory.java
+++ b/plugins/customization/org.eclipse.papyrus.customization/src/org/eclipse/papyrus/customization/modelelement/CustomizationModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.customization.modelelement;
@@ -17,14 +19,14 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.customization.Activator;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
+import org.eclipse.papyrus.views.properties.modelelement.EMFModelElement;
import org.eclipse.papyrus.views.properties.modelelement.EMFModelElementFactory;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
public class CustomizationModelElementFactory extends EMFModelElementFactory {
@Override
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ protected EMFModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSModelElementFactory.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSModelElementFactory.java
index d71749709c0..b20a7c20261 100644
--- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSModelElementFactory.java
+++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.css.properties.modelelement;
@@ -16,14 +18,15 @@ import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.infra.gmfdiag.css.properties.Activator;
+import org.eclipse.papyrus.infra.gmfdiag.properties.modelelement.CustomStyleModelElement;
+import org.eclipse.papyrus.infra.gmfdiag.properties.modelelement.CustomStyleModelElementFactory;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
-public class CSSModelElementFactory implements ModelElementFactory {
+public class CSSModelElementFactory extends CustomStyleModelElementFactory {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected CustomStyleModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View view = NotationHelper.findView(sourceElement);
if(view == null) {
Activator.log.warn("The selected element cannot be resolved to a GMF View");
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSPreferencesModelElementFactory.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSPreferencesModelElementFactory.java
index d335bb1eb20..e7ee6f2327f 100644
--- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSPreferencesModelElementFactory.java
+++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSPreferencesModelElementFactory.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,18 +8,20 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.css.properties.modelelement;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
+import org.eclipse.papyrus.views.properties.modelelement.PreferencesModelElement;
import org.eclipse.papyrus.views.properties.modelelement.PreferencesModelElementFactory;
public class CSSPreferencesModelElementFactory extends PreferencesModelElementFactory {
@Override
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ protected PreferencesModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
return new CSSPreferencesModelElement(context);
}
}
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElement.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElement.java
index 6d54d2890d9..5be7b852581 100644
--- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElement.java
+++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElement.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
+ * Copyright (c) 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
@@ -7,7 +7,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation
+ * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.css.properties.modelelement;
@@ -17,7 +19,6 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.papyrus.infra.gmfdiag.css.properties.provider.CSSStyleSheetLabelProvider;
import org.eclipse.papyrus.views.properties.modelelement.EMFModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
/**
@@ -27,7 +28,7 @@ import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
* @author gpascual
*
*/
-public class CSSThemesModelElement extends EMFModelElement implements ModelElement {
+public class CSSThemesModelElement extends EMFModelElement {
/** UI view path for theme style sheets. */
private static final String THEME_STYLESHEETS_PATH = "stylesheets"; //$NON-NLS-1$
diff --git a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElementFactory.java b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElementFactory.java
index ade28c59815..f486fb3b640 100644
--- a/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElementFactory.java
+++ b/plugins/infra/gmfdiag/css/org.eclipse.papyrus.infra.gmfdiag.css.properties/src/org/eclipse/papyrus/infra/gmfdiag/css/properties/modelelement/CSSThemesModelElementFactory.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
+ * Copyright (c) 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
@@ -7,7 +7,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation
+ * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.css.properties.modelelement;
@@ -17,8 +19,7 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractEMFModelElementFactory;
/**
@@ -28,7 +29,7 @@ import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
* @author gpascual
*
*/
-public class CSSThemesModelElementFactory implements ModelElementFactory {
+public class CSSThemesModelElementFactory extends AbstractEMFModelElementFactory<CSSThemesModelElement> {
/**
@@ -39,15 +40,8 @@ public class CSSThemesModelElementFactory implements ModelElementFactory {
super();
}
- /**
- * @see org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory#createFromSource(java.lang.Object,
- * org.eclipse.papyrus.views.properties.contexts.DataContextElement)
- *
- * @param sourceElement
- * @param context
- * @return
- */
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected CSSThemesModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/AppearanceModelElementFactory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/AppearanceModelElementFactory.java
index 11f5520683c..de8b9efcdd8 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/AppearanceModelElementFactory.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/AppearanceModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElementFactory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElementFactory.java
index 87769b7b6d4..a2c8553afea 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElementFactory.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/CustomStyleModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
@@ -17,13 +19,13 @@ import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.infra.gmfdiag.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractEMFModelElementFactory;
-public class CustomStyleModelElementFactory implements ModelElementFactory {
+public class CustomStyleModelElementFactory extends AbstractEMFModelElementFactory<CustomStyleModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected CustomStyleModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View view = NotationHelper.findView(sourceElement);
if(view != null) {
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElementFactory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElementFactory.java
index e549d8f8dd4..3b7b2cc602b 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElementFactory.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/DecoratedModelElementFactory.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,25 +8,28 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.providers.ShapeDecorator;
import org.eclipse.papyrus.infra.gmfdiag.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
/**
* A factory for handling the GMF decorated elements
*/
-public class DecoratedModelElementFactory implements ModelElementFactory {
+public class DecoratedModelElementFactory extends AbstractModelElementFactory<DecoratedModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected DecoratedModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View view = NotationHelper.findView(sourceElement);
if(view != null) {
@@ -34,11 +37,20 @@ public class DecoratedModelElementFactory implements ModelElementFactory {
if(ShapeDecorator.isDecorable(view)) {
return new DecoratedModelElement(view, domain);
}
-
+
}
Activator.log.warn("The selected element cannot be resolved to a Decorated element");
return null;
}
+ @Override
+ protected void updateModelElement(DecoratedModelElement modelElement, Object newSourceElement) {
+ View view = NotationHelper.findView(newSourceElement);
+ if((view == null) || !ShapeDecorator.isDecorable(view)) {
+ throw new IllegalArgumentException("Cannot resolve decorable View selection: " + newSourceElement);
+ }
+ modelElement.source = view;
+ modelElement.domain = EMFHelper.resolveEditingDomain(view);
+ }
}
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 6a0889ccf7d..a0895d13c2d 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
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
@@ -21,17 +22,18 @@ 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;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractEMFModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElement;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
/**
* A factory for handling the GMF Notation elements
*
* @author Camille Letavernier
*/
-public class NotationModelElementFactory implements ModelElementFactory {
-
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+public class NotationModelElementFactory extends AbstractModelElementFactory<AbstractModelElement> {
+ @Override
+ protected AbstractModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
if (sourceElement instanceof ObservableGradientData) {
ObservableGradientData gradientData = (ObservableGradientData)sourceElement;
@@ -50,4 +52,34 @@ public class NotationModelElementFactory implements ModelElementFactory {
return null;
}
+ @Override
+ protected void updateModelElement(AbstractModelElement modelElement, Object newSourceElement) {
+ if(modelElement instanceof GMFModelElement) {
+ updateModelElement((GMFModelElement)modelElement, newSourceElement);
+ } else if(modelElement instanceof GradientDataModelElement) {
+ updateModelElement((GradientDataModelElement)modelElement, newSourceElement);
+ }
+ }
+
+ void updateModelElement(GradientDataModelElement modelElement, Object newSourceElement) {
+ if(newSourceElement instanceof ObservableGradientData) {
+ ObservableGradientData ogd = (ObservableGradientData)newSourceElement;
+ modelElement.sourceElement = ogd;
+ modelElement.owner = ogd.getOwner();
+ } else if(newSourceElement instanceof GradientData) {
+ modelElement.sourceElement = (GradientData)newSourceElement;
+ modelElement.owner = null;
+ } else {
+ throw new IllegalArgumentException("Cannot resolve GradientData selection: " + newSourceElement);
+ }
+ }
+
+ void updateModelElement(GMFModelElement modelElement, Object newSourceElement) {
+ View view = NotationHelper.findView(newSourceElement);
+ if(view == null) {
+ throw new IllegalArgumentException("Cannot resolve View selection: " + newSourceElement);
+ }
+
+ AbstractEMFModelElementFactory.updateEMFModelElement(modelElement, view);
+ }
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulerAndGridModelElement.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulerAndGridModelElement.java
index 87f0f8cfd2b..cae3f549ea8 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulerAndGridModelElement.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulerAndGridModelElement.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
* are made available under the terms of the Eclipse Public License v1.0
@@ -7,8 +7,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- *
- * CEA LIST - Initial API and implementation
+ *
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
@@ -47,12 +48,12 @@ public class RulerAndGridModelElement extends AbstractModelElement {
/**
* the diagram for which we are editing preferences
*/
- private Diagram diagram;
+ protected Diagram diagram;
/**
* the edited preference store
*/
- private IPreferenceStore store;
+ protected IPreferenceStore store;
/**
*
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulersAndGridModelElementFactory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulersAndGridModelElementFactory.java
index 0709999a89e..8b7e6e1abfe 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulersAndGridModelElementFactory.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.properties/src/org/eclipse/papyrus/infra/gmfdiag/properties/modelelement/RulersAndGridModelElementFactory.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
* are made available under the terms of the Eclipse Public License v1.0
@@ -7,8 +7,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- *
- * CEA LIST - Initial API and implementation
+ *
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.properties.modelelement;
@@ -23,26 +24,17 @@ import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
import org.eclipse.papyrus.infra.gmfdiag.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
/**
*
* @author vl222926
* The factory used to edit Rulers and Grid properties
*/
-public class RulersAndGridModelElementFactory implements ModelElementFactory {
+public class RulersAndGridModelElementFactory extends AbstractModelElementFactory<RulerAndGridModelElement> {
- /**
- *
- * @see org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory#createFromSource(java.lang.Object,
- * org.eclipse.papyrus.views.properties.contexts.DataContextElement)
- *
- * @param sourceElement
- * @param context
- * @return
- */
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected RulerAndGridModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
if(sourceElement instanceof EditPart) {
final IPreferenceStore preferenceStore = DiagramEditPartsUtil.getDiagramWorkspacePreferenceStore((EditPart)sourceElement);
View view = NotationHelper.findView(DiagramEditPartsUtil.getDiagramEditPart((EditPart)sourceElement));
@@ -56,6 +48,14 @@ public class RulersAndGridModelElementFactory implements ModelElementFactory {
return null;
}
-
+ @Override
+ protected void updateModelElement(RulerAndGridModelElement modelElement, Object newSourceElement) {
+ if(!(newSourceElement instanceof EditPart)) {
+ throw new IllegalArgumentException("Cannot resolve EditPart selection: " + newSourceElement);
+ }
+ EditPart editPart = (EditPart)newSourceElement;
+ modelElement.store = DiagramEditPartsUtil.getDiagramWorkspacePreferenceStore(editPart);
+ modelElement.diagram = (Diagram)NotationHelper.findView(DiagramEditPartsUtil.getDiagramEditPart(editPart));
+ }
}
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableFactory.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableFactory.java
index 11b51492418..0c7e6645c70 100644
--- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableFactory.java
+++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.properties/src/org/eclipse/papyrus/infra/nattable/properties/modelelement/NatTableFactory.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 417409
*
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.properties.modelelement;
@@ -20,23 +20,14 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.nattable.model.nattable.Table;
import org.eclipse.papyrus.infra.nattable.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
+import org.eclipse.papyrus.views.properties.modelelement.EMFModelElement;
import org.eclipse.papyrus.views.properties.modelelement.EMFModelElementFactory;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
public class NatTableFactory extends EMFModelElementFactory {
- /**
- *
- * @see org.eclipse.papyrus.views.properties.modelelement.EMFModelElementFactory#createFromSource(java.lang.Object,
- * org.eclipse.papyrus.views.properties.contexts.DataContextElement)
- *
- * @param sourceElement
- * @param context
- * @return
- */
@Override
- public ModelElement createFromSource(final Object sourceElement, final DataContextElement context) {
+ protected EMFModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$
@@ -46,7 +37,7 @@ public class NatTableFactory extends EMFModelElementFactory {
EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(source);
return new NatTableModelElement((Table)source, domain);
} else {
- return super.createFromSource(sourceElement, context);
+ return super.doCreateFromSource(sourceElement, context);
}
}
}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/META-INF/MANIFEST.MF b/plugins/infra/org.eclipse.papyrus.infra.tools/META-INF/MANIFEST.MF
index 69b756e3f75..b2b0b9839a1 100644
--- a/plugins/infra/org.eclipse.papyrus.infra.tools/META-INF/MANIFEST.MF
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/META-INF/MANIFEST.MF
@@ -13,7 +13,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.emf.ecore;bundle-version="2.9.0",
org.eclipse.emf.ecore.xmi;bundle-version="2.9.0",
org.eclipse.emf.edit;bundle-version="2.9.0",
- org.eclipse.core.expressions;bundle-version="3.4.500"
+ org.eclipse.core.expressions;bundle-version="3.4.500",
+ com.google.guava;bundle-version="11.0.0"
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
Bundle-Version: 1.0.0.qualifier
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingInvocationHandler.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingInvocationHandler.java
new file mode 100644
index 00000000000..6dd91f9e37b
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingInvocationHandler.java
@@ -0,0 +1,174 @@
+/*
+ * 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.tools.databinding;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.databinding.observable.IObservable;
+
+
+/**
+ * An invocation handler for dynamic proxies that wrap {@link DelegatingObservable}s to implement other interfaces of those delegators' delegates,
+ * such as the papyrus {@code ICommitListener} interface from the Widgets API.
+ */
+class DelegatingInvocationHandler implements InvocationHandler {
+
+ private final IDelegatingObservable delegator;
+
+ private final Class<? extends IObservable> delegatedInterface;
+
+ private DelegatingInvocationHandler(IDelegatingObservable delegator, Class<? extends IObservable> delegatedInterface) {
+ super();
+
+ this.delegator = delegator;
+ this.delegatedInterface = delegatedInterface;
+ }
+
+ public static <T extends IObservable> T wrap(IDelegatingObservable delegator, Class<T> delegatedInterface) {
+ T result;
+
+ List<Class<?>> mixins = null;
+
+ IObservable delegate = delegator.getDelegate();
+
+ for(Class<?> next : allInterfaces(delegate.getClass())) {
+ // Already have the core observable interfaces covered
+ if(!next.isAssignableFrom(delegatedInterface)) {
+ if(mixins == null) {
+ mixins = new ArrayList<Class<?>>(1);
+ }
+ mixins.add(next);
+ }
+ }
+
+ if(mixins == null) {
+ result = delegatedInterface.cast(delegator);
+ } else {
+ // This class loader is sure to be able to see all of the interfaces implemented by the delegate.
+ // But the question is, can it see the IDelegatingObservable interface?
+ ClassLoader loader = delegator.getDelegate().getClass().getClassLoader();
+ try {
+ if(loader.loadClass(IDelegatingObservable.class.getName()) != IDelegatingObservable.class) {
+ // This loader can't see the same class. Use my loader, instead
+ loader = DelegatingInvocationHandler.class.getClassLoader();
+ }
+ } catch (Exception e) {
+ // This loader can't see the class. Use my loader, instead
+ loader = DelegatingInvocationHandler.class.getClassLoader();
+ }
+
+ result = wrap(delegator, delegatedInterface, loader, mixins.toArray(new Class<?>[mixins.size()]));
+ }
+
+ return result;
+ }
+
+ static Set<Class<?>> allInterfaces(Class<?> clazz) {
+ Set<Class<?>> result = new HashSet<Class<?>>();
+ collectAllInterfaces(clazz, result);
+ return result;
+ }
+
+ private static void collectAllInterfaces(Class<?> clazz, Collection<Class<?>> result) {
+ Class<?>[] interfaces = clazz.getInterfaces();
+ for(int i = 0; i < interfaces.length; i++) {
+ // Don't need to collect super-interfaces because they are inherited
+ result.add(interfaces[i]);
+ }
+
+ // Climb the type hierarchy to get interfaces of superclasses (which may be unrelated to direct interfaces)
+ Class<?> zuper = clazz.getSuperclass();
+ if(zuper != null) {
+ collectAllInterfaces(zuper, result);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T extends IObservable> T wrap(IDelegatingObservable delegator, Class<T> delegatedInterface, ClassLoader loader, Class<?>... mixins) {
+ T result;
+
+ if((loader == null) || (mixins.length == 0)) {
+ // Nothing to wrap
+ result = delegatedInterface.cast(delegator);
+ } else {
+ List<Class<?>> interfaces = new ArrayList<Class<?>>(mixins.length + 2);
+ interfaces.add(delegatedInterface);
+ interfaces.add(IDelegatingObservable.class);
+ interfaces.addAll(Arrays.asList(mixins));
+ InvocationHandler handler = new DelegatingInvocationHandler(delegator, delegatedInterface);
+
+ result = delegatedInterface.cast(Proxy.newProxyInstance(loader, interfaces.toArray(new Class<?>[interfaces.size()]), handler));
+ ((DelegatingObservable<T>)delegator).setRealObservable(result);
+ }
+
+ return result;
+ }
+
+ /**
+ * The interesting case of wrapping an observable that is already one of our delegating dynamic proxies.
+ *
+ * @param proxy
+ * a dynamic proxy implementing the {@link IDelegatingObservable} interface
+ *
+ * @return another dynamic proxy of the same class, which delegates to the supplied {@code proxy}
+ *
+ * @throws Exception
+ * on failure to create a new dynamic proxy of the same kind as the delegate {@code proxy}
+ */
+ @SuppressWarnings("unchecked")
+ static <T extends IObservable> T wrapDynamicProxy(T proxy) throws Exception {
+ final DelegatingInvocationHandler proxyHandler = (DelegatingInvocationHandler)Proxy.getInvocationHandler(proxy);
+
+ // Create a new delegator of the appropriate class
+ DelegatingObservable<T> proxyDelegator = (DelegatingObservable<T>)proxyHandler.delegator;
+ DelegatingObservable<T> delegator = proxyDelegator.getClass().getDeclaredConstructor(proxyHandler.delegatedInterface).newInstance(proxy);
+
+ // Create an invocation handler for the same delegated interface as the wrapped proxy
+ DelegatingInvocationHandler handler = new DelegatingInvocationHandler(delegator, proxyHandler.delegatedInterface);
+
+ // And create a new delegating proxy of the same class
+ return (T)proxy.getClass().getDeclaredConstructor(InvocationHandler.class).newInstance(handler);
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ Object result = null;
+
+ Class<?> owner = method.getDeclaringClass();
+
+ try {
+ if((owner == delegatedInterface) || (owner == IDelegatingObservable.class) || (owner == ReferenceCountedObservable.class) || (owner == Object.class) || owner.isAssignableFrom(delegatedInterface)) {
+ // Refer this to our delegate
+ result = method.invoke(delegator, args);
+ } else {
+ // Refer this to the delegator's delegate
+ result = method.invoke(delegator.getDelegate(), args);
+ }
+ } catch (InvocationTargetException e) {
+ // Don't just re-throw this because chances are it's triggered by a run-time exception (doesn't need to
+ // be declared) or by a declared exception. The ITE type is not usually declared in API signatures
+ // (in fact, it really should only be declared by the Method::invoke(...) API!)
+ throw e.getTargetException();
+ }
+
+ return result;
+ }
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservable.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservable.java
new file mode 100644
index 00000000000..55393927999
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservable.java
@@ -0,0 +1,348 @@
+/*
+ * 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.tools.databinding;
+
+import java.lang.reflect.Proxy;
+
+import org.eclipse.core.databinding.observable.ChangeEvent;
+import org.eclipse.core.databinding.observable.DisposeEvent;
+import org.eclipse.core.databinding.observable.IChangeListener;
+import org.eclipse.core.databinding.observable.IDisposeListener;
+import org.eclipse.core.databinding.observable.IObservable;
+import org.eclipse.core.databinding.observable.IObserving;
+import org.eclipse.core.databinding.observable.IStaleListener;
+import org.eclipse.core.databinding.observable.ObservableEvent;
+import org.eclipse.core.databinding.observable.ObservableTracker;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.StaleEvent;
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+
+
+/**
+ * Abstract implementation of the {@link IDelegatingObservable} protocol with factory methods for creation of delegators.
+ *
+ * @see #wrap(IObservable)
+ * @see #create(Realm, Class)
+ * @see #create(Realm, Class, ClassLoader, Class...)
+ */
+public abstract class DelegatingObservable<T extends IObservable> extends ReferenceCountedObservable.Abstract implements IDelegatingObservable {
+
+ private final Class<T> delegateType;
+
+ private T delegate;
+
+ @SuppressWarnings("unchecked")
+ private T realObservable = (T)this;
+
+ private IChangeListener forwardingChangeListener;
+
+ private IStaleListener forwardingStaleListener;
+
+ private IDisposeListener delegateDisposeListener;
+
+ DelegatingObservable(T delegate, Class<T> delegateType) {
+ super(delegate.getRealm());
+
+ this.delegateType = delegateType;
+
+ setDelegate(delegate);
+ }
+
+ DelegatingObservable(Realm realm, Class<T> delegateType) {
+ super(realm);
+
+ this.delegateType = delegateType;
+ }
+
+ /**
+ * Wraps an {@code observable} in a delegator, returning an {@link IDelegatingObservable} of the appropriate kind.
+ *
+ * @param observable
+ * an observable to wrap in a delegator
+ * @return the delegator, which will be an instance of the {@link IDelegatingObservable} interface
+ *
+ * @throws IllegalArgumentException
+ * if the {@code observable} is of a kind for which no delegator is currently implemented
+ */
+ public static IObservable wrap(IObservable observable) {
+ IObservable result;
+
+ if(Proxy.isProxyClass(observable.getClass()) && (Proxy.getInvocationHandler(observable) instanceof DelegatingInvocationHandler)) {
+ // Already have a delegator and it's a dynamic proxy. Just create another like it
+ try {
+ result = DelegatingInvocationHandler.wrapDynamicProxy(observable);
+ } catch (Exception e) {
+ // Seems unlikely as I must have created the observable in the first place
+ throw new IllegalArgumentException("observable is an invalid implementation of IDelegatingObservable", e); //$NON-NLS-1$
+ }
+ } else if(observable instanceof IObservableList) {
+ result = DelegatingObservableList.wrap((IObservableList)observable);
+ } else if(observable instanceof IObservableSet) {
+ result = DelegatingObservableSet.wrap((IObservableSet)observable);
+ } else if(observable instanceof IObservableValue) {
+ result = DelegatingObservableValue.wrap((IObservableValue)observable);
+ } else {
+ throw new IllegalArgumentException("no delegating wrapper implementation available for observable"); //$NON-NLS-1$
+ }
+
+ return result;
+ }
+
+ /**
+ * Creates a new empty delegator suitable for observables of the specified type without any other mix-in interfaces such as {@link IObserving}.
+ * Observable types must be specified by their abstract interface, and currently the following types are supported:
+ * <ul>
+ * <li>{@link IObservableValue}</li>
+ * <li>{@link IObservableList}</li>
+ * <li>{@link IObservableSet}</li>
+ * </ul>
+ *
+ * @param observableType
+ * the kind of observable that will be the new delegator's delegate
+ * @return the delegator, which will be an instance of the {@link IDelegatingObservable} interface
+ *
+ * @throws IllegalArgumentException
+ * if the {@code observable} is of a kind for which no delegator is currently implemented
+ *
+ * @see #create(Realm, Class, ClassLoader, Class...)
+ */
+ public static <T extends IObservable> T create(Realm realm, Class<T> observableType) {
+ return create(realm, observableType, null); // Class loader not needed without any mix-ins
+ }
+
+ /**
+ * Creates a new empty delegator suitable for observables of the specified type with optional mix-in interfaces such as {@link IObserving},
+ * which is implemented by detail observables in a master/detail relationship. Observable types must be specified
+ * by their abstract interface, and currently the following types are supported:
+ * <ul>
+ * <li>{@link IObservableValue}</li>
+ * <li>{@link IObservableList}</li>
+ * <li>{@link IObservableSet}</li>
+ * </ul>
+ *
+ * @param observableType
+ * the kind of observable that will be the new delegator's delegate
+ * @param loader
+ * a class loader that can see all of the {@code mixins}, if any
+ * @param mixins
+ * optional mix-in interfaces that the resulting observable should refer to its delegate. These must all have
+ * {@linkplain #registerMixinHandler handlers already registered}
+ * @return the delegator, which will be an instance of the {@link IDelegatingObservable} interface
+ *
+ * @throws IllegalArgumentException
+ * if the {@code observable} is of a kind for which no delegator is currently implemented
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends IObservable> T create(Realm realm, Class<T> observableType, ClassLoader loader, Class<?>... mixins) {
+ if(observableType == IObservableList.class) {
+ return (T)DelegatingObservableList.create(realm, loader, mixins);
+ } else if(observableType == IObservableSet.class) {
+ return (T)DelegatingObservableSet.create(realm, loader, mixins);
+ } else if(observableType == IObservableValue.class) {
+ return (T)DelegatingObservableValue.create(realm, loader, mixins);
+ } else {
+ throw new IllegalArgumentException("observableType"); //$NON-NLS-1$
+ }
+ }
+
+ public final void setDelegate(final IObservable delegate) {
+ if(isDisposed()) {
+ throw new IllegalStateException("disposed"); //$NON-NLS-1$
+ }
+
+ final T oldDelegate = this.delegate;
+
+ if(delegate != oldDelegate) {
+ final T newDelegate = (delegate == null) ? null : delegateType.cast(delegate);
+
+ if(oldDelegate != null) {
+ unhookDelegate(oldDelegate);
+
+ // Release it only after this iteration of the event loop so that UI refreshes can still access it for now
+ // in case its retain count will go to zero and it will be disposed
+ ReferenceCountedObservable.Util.autorelease(oldDelegate);
+ }
+
+ this.delegate = newDelegate;
+
+ if(newDelegate != null) {
+ ReferenceCountedObservable.Util.retain(newDelegate);
+ hookDelegate(newDelegate);
+ }
+
+ delegateChanged(oldDelegate, newDelegate);
+ }
+ }
+
+ final void clearDelegate() {
+ // Can do this even if disposed
+
+ if(delegate != null) {
+ unhookDelegate(delegate);
+
+ delegate = null;
+
+ // Let listeners know that we've changed. We cannot fire an accurate value change event
+ // because we can no longer access the old delegate's value, as it is now disposed
+ fireChange();
+ }
+ }
+
+ public final T getDelegate() {
+ return delegate;
+ }
+
+ /**
+ * Notifies of a change from one delegate to another. Subclasses overriding this must call {@code super}.
+ *
+ * @param oldDelegate
+ * the previous delegate, or {@code null} if there was none
+ * @param newDelegate
+ * the new delegate, or {@code null} if now I have none
+ */
+ protected void delegateChanged(T oldDelegate, T newDelegate) {
+ fireChange();
+ }
+
+ protected void hookDelegate(T delegate) {
+ delegate.addChangeListener(getForwardingChangeListener());
+ delegate.addStaleListener(getForwardingStaleListener());
+
+ // Don't forward dispose events because the delegate has its own lifecycle. However, when our delegate
+ // is disposed, we forget about it
+ delegate.addDisposeListener(getDelegateDisposeListener());
+ }
+
+ protected void unhookDelegate(T delegate) {
+ delegate.removeChangeListener(getForwardingChangeListener());
+ delegate.removeStaleListener(getForwardingStaleListener());
+ delegate.removeDisposeListener(getDelegateDisposeListener());
+ }
+
+ public boolean isStale() {
+ getterCalled();
+
+ return (delegate != null) && delegate.isStale();
+ }
+
+ protected void getterCalled() {
+ ObservableTracker.getterCalled(getRealObservable());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return (obj == this) || ((delegate == null) ? false : delegate.equals(obj));
+ }
+
+ @Override
+ public int hashCode() {
+ return (delegate == null) ? 0 : delegate.hashCode();
+ }
+
+ /**
+ * Sets the real observable (which may be a dynamic proxy) to report as the source of events and the target of getter calls in the
+ * {@link ObservableTracker}.
+ *
+ * @param realObservable
+ * my event source
+ */
+ final void setRealObservable(T realObservable) {
+ this.realObservable = realObservable;
+ }
+
+ /**
+ * Gets the source to report for events (which may be a dynamic proxy).
+ *
+ * @return my event source
+ */
+ final T getRealObservable() {
+ return realObservable;
+ }
+
+ @Override
+ protected final void fireChange() {
+ fireEvent(new ChangeEvent(getRealObservable()));
+ }
+
+ @Override
+ protected final void fireStale() {
+ fireEvent(new StaleEvent(getRealObservable()));
+ }
+
+ public void dispose() {
+ if(!isDisposed()) {
+ if(delegate != null) {
+ unhookDelegate(delegate);
+
+ // Release it only after this iteration of the event loop so that UI refreshes can still access it for now
+ // in case its retain count will go to zero and it will be disposed
+ ReferenceCountedObservable.Util.autorelease(delegate);
+ delegate = null;
+ }
+ super.dispose();
+ }
+ }
+
+ @Override
+ protected void fireEvent(ObservableEvent event) {
+ // ensure the correct source for events fired by the superclass
+ if((event instanceof DisposeEvent) && (event.getSource() != getRealObservable())) {
+ event = new DisposeEvent(getRealObservable());
+ }
+
+ super.fireEvent(event);
+ }
+
+ private IChangeListener getForwardingChangeListener() {
+ if(forwardingChangeListener == null) {
+ forwardingChangeListener = new IChangeListener() {
+
+ public void handleChange(ChangeEvent event) {
+ DelegatingObservable.this.fireChange();
+ }
+ };
+ }
+
+ return forwardingChangeListener;
+ }
+
+ private IStaleListener getForwardingStaleListener() {
+ if(forwardingStaleListener == null) {
+ forwardingStaleListener = new IStaleListener() {
+
+ public void handleStale(StaleEvent staleEvent) {
+ DelegatingObservable.this.fireStale();
+ }
+ };
+ }
+
+ return forwardingStaleListener;
+ }
+
+ private IDisposeListener getDelegateDisposeListener() {
+ if(delegateDisposeListener == null) {
+ delegateDisposeListener = new IDisposeListener() {
+
+ public void handleDispose(DisposeEvent event) {
+ if(event.getObservable() == getDelegate()) {
+ clearDelegate();
+ }
+ }
+ };
+ }
+
+ return delegateDisposeListener;
+ }
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableCollection.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableCollection.java
new file mode 100644
index 00000000000..f4597404f19
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableCollection.java
@@ -0,0 +1,131 @@
+/*
+ * 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.tools.databinding;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.eclipse.core.databinding.observable.IObservableCollection;
+import org.eclipse.core.databinding.observable.Realm;
+
+
+/**
+ * This is the DelegatingObservableCollection type. Enjoy.
+ */
+public abstract class DelegatingObservableCollection<T extends IObservableCollection> extends DelegatingObservable<T> implements IObservableCollection {
+
+ private static final Object[] EMPTY_ARRAY = {};
+
+ DelegatingObservableCollection(T delegate, Class<T> delegateType) {
+ super(delegate, delegateType);
+ }
+
+ DelegatingObservableCollection(Realm realm, Class<T> delegateType) {
+ super(realm, delegateType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ getterCalled();
+
+ return super.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ getterCalled();
+
+ return super.hashCode();
+ }
+
+ public int size() {
+ getterCalled();
+
+ return (getDelegate() == null) ? 0 : getDelegate().size();
+ }
+
+ public boolean isEmpty() {
+ getterCalled();
+
+ return (getDelegate() == null) ? true : getDelegate().isEmpty();
+ }
+
+ public boolean contains(Object o) {
+ getterCalled();
+
+ return (getDelegate() == null) ? false : getDelegate().contains(o);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Iterator iterator() {
+ getterCalled();
+
+ return (getDelegate() == null) ? Collections.EMPTY_LIST.iterator() : getDelegate().iterator();
+ }
+
+ public Object[] toArray() {
+ getterCalled();
+
+ return (getDelegate() == null) ? EMPTY_ARRAY : getDelegate().toArray();
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object[] toArray(Object[] a) {
+ getterCalled();
+
+ return (getDelegate() == null) ? Collections.EMPTY_LIST.toArray(a) : getDelegate().toArray(a);
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean add(Object e) {
+ return (getDelegate() == null) ? false : getDelegate().add(e);
+ }
+
+ public boolean remove(Object o) {
+ return (getDelegate() == null) ? false : getDelegate().remove(o);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public boolean containsAll(Collection c) {
+ getterCalled();
+
+ return (getDelegate() == null) ? false : getDelegate().containsAll(c);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public boolean addAll(Collection c) {
+ return (getDelegate() == null) ? false : getDelegate().addAll(c);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public boolean removeAll(Collection c) {
+ return (getDelegate() == null) ? false : getDelegate().removeAll(c);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public boolean retainAll(Collection c) {
+ return (getDelegate() == null) ? false : getDelegate().retainAll(c);
+ }
+
+ public void clear() {
+ if(getDelegate() != null) {
+ getDelegate().clear();
+ }
+ }
+
+ public Object getElementType() {
+ return (getDelegate() == null) ? null : getDelegate().getElementType();
+ }
+
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableList.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableList.java
new file mode 100644
index 00000000000..2c7e7807aaa
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableList.java
@@ -0,0 +1,205 @@
+/*
+ * 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.tools.databinding;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.core.databinding.observable.Diffs;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.list.IListChangeListener;
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.list.ListChangeEvent;
+import org.eclipse.core.databinding.observable.list.ListDiff;
+
+
+/**
+ * This is the DelegatingObservableList type. Enjoy.
+ */
+public class DelegatingObservableList extends DelegatingObservableCollection<IObservableList> implements IObservableList {
+
+ private static final Object LIST_EVENT_TYPE = new Object();
+
+ private IListChangeListener forwardingListChangeListener;
+
+ DelegatingObservableList(IObservableList delegate) {
+ super(delegate, IObservableList.class);
+ }
+
+ DelegatingObservableList(Realm realm) {
+ super(realm, IObservableList.class);
+ }
+
+ public static IObservableList wrap(IObservableList observable) {
+ IObservableList result;
+
+ if(observable instanceof IDelegatingObservable) {
+ // Already have a delegator. Just create another like it
+ try {
+ result = (IObservableList)observable.getClass().getDeclaredConstructor(IObservableList.class).newInstance(observable);
+ } catch (Exception e) {
+ // Seems unlikely as I must have created the observable in the first place
+ throw new IllegalArgumentException("observable is an invalid implementation of IDelegatingObservable", e); //$NON-NLS-1$
+ }
+ } else {
+ result = DelegatingInvocationHandler.wrap(new DelegatingObservableList(observable), IObservableList.class);
+ }
+
+ return result;
+ }
+
+ public static IObservableList create(Realm realm, ClassLoader loader, Class<?>... mixins) {
+ return DelegatingInvocationHandler.wrap(new DelegatingObservableList(realm), IObservableList.class, loader, mixins);
+ }
+
+ public void addListChangeListener(IListChangeListener listener) {
+ addListener(LIST_EVENT_TYPE, listener);
+ }
+
+ public void removeListChangeListener(IListChangeListener listener) {
+ removeListener(LIST_EVENT_TYPE, listener);
+ }
+
+ @Override
+ protected void hookDelegate(IObservableList delegate) {
+ super.hookDelegate(delegate);
+ delegate.addListChangeListener(getForwardingListChangeListener());
+ }
+
+ @Override
+ protected void unhookDelegate(IObservableList delegate) {
+ delegate.removeListChangeListener(getForwardingListChangeListener());
+ super.unhookDelegate(delegate);
+ }
+
+ @Override
+ protected void delegateChanged(IObservableList oldDelegate, IObservableList newDelegate) {
+ super.delegateChanged(oldDelegate, newDelegate);
+
+ List<?> oldList = ((oldDelegate == null) || oldDelegate.isDisposed()) ? Collections.EMPTY_LIST : oldDelegate;
+ List<?> newList = (newDelegate == null) ? Collections.EMPTY_LIST : newDelegate;
+
+ fireEvent(new MyListChangeEvent(Diffs.computeListDiff(oldList, newList)));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void add(int index, Object element) {
+ if(getDelegate() == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ getDelegate().add(index, element);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public boolean addAll(int index, Collection c) {
+ if(getDelegate() == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getDelegate().addAll(index, c);
+ }
+
+ public Object get(int index) {
+ getterCalled();
+
+ if(getDelegate() == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getDelegate().get(index);
+ }
+
+ public Object set(int index, Object element) {
+ if(getDelegate() == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getDelegate().set(index, element);
+ }
+
+ public Object move(int oldIndex, int newIndex) {
+ if(getDelegate() == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getDelegate().move(oldIndex, newIndex);
+ }
+
+ public Object remove(int index) {
+ return (getDelegate() == null) ? Collections.EMPTY_LIST.remove(index) : getDelegate().remove(index);
+ }
+
+ public int indexOf(Object o) {
+ getterCalled();
+
+ return (getDelegate() == null) ? -1 : getDelegate().indexOf(o);
+ }
+
+ public int lastIndexOf(Object o) {
+ getterCalled();
+
+ return (getDelegate() == null) ? -1 : getDelegate().lastIndexOf(o);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public ListIterator listIterator() {
+ getterCalled();
+
+ return (getDelegate() == null) ? Collections.EMPTY_LIST.listIterator() : getDelegate().listIterator();
+ }
+
+ @SuppressWarnings("rawtypes")
+ public ListIterator listIterator(int index) {
+ getterCalled();
+
+ return (getDelegate() == null) ? Collections.EMPTY_LIST.listIterator(index) : getDelegate().listIterator(index);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public List subList(int fromIndex, int toIndex) {
+ getterCalled();
+
+ return (getDelegate() == null) ? Collections.EMPTY_LIST.subList(fromIndex, toIndex) : getDelegate().subList(fromIndex, toIndex);
+ }
+
+ private IListChangeListener getForwardingListChangeListener() {
+ if(forwardingListChangeListener == null) {
+ forwardingListChangeListener = new IListChangeListener() {
+
+ public void handleListChange(ListChangeEvent event) {
+ ListChangeEvent myEvent = new MyListChangeEvent(event.diff);
+ fireEvent(myEvent);
+ }
+ };
+ }
+
+ return forwardingListChangeListener;
+ }
+
+ //
+ // Nested types
+ //
+
+ class MyListChangeEvent extends ListChangeEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ MyListChangeEvent(ListDiff diff) {
+ super(getRealObservable(), diff);
+ }
+
+ @Override
+ protected Object getListenerType() {
+ // We implement our own listener type because the type from the core framework is not accessible
+ return LIST_EVENT_TYPE;
+ }
+ }
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableSet.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableSet.java
new file mode 100644
index 00000000000..4111577f027
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableSet.java
@@ -0,0 +1,128 @@
+/*
+ * 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.tools.databinding;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.core.databinding.observable.Diffs;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.databinding.observable.set.ISetChangeListener;
+import org.eclipse.core.databinding.observable.set.SetChangeEvent;
+import org.eclipse.core.databinding.observable.set.SetDiff;
+
+
+/**
+ * This is the DelegatingObservableSet type. Enjoy.
+ */
+public class DelegatingObservableSet extends DelegatingObservableCollection<IObservableSet> implements IObservableSet {
+
+ private static final Object SET_EVENT_TYPE = new Object();
+
+ private ISetChangeListener forwardingSetChangeListener;
+
+ DelegatingObservableSet(IObservableSet delegate) {
+ super(delegate, IObservableSet.class);
+ }
+
+ DelegatingObservableSet(Realm realm) {
+ super(realm, IObservableSet.class);
+ }
+
+ public static IObservableSet wrap(IObservableSet observable) {
+ IObservableSet result;
+
+ if(observable instanceof IDelegatingObservable) {
+ // Already have a delegator. Just create another like it
+ try {
+ result = (IObservableSet)observable.getClass().getDeclaredConstructor(IObservableSet.class).newInstance(observable);
+ } catch (Exception e) {
+ // Seems unlikely as I must have created the observable in the first place
+ throw new IllegalArgumentException("observable is an invalid implementation of IDelegatingObservable", e); //$NON-NLS-1$
+ }
+ } else {
+ result = DelegatingInvocationHandler.wrap(new DelegatingObservableSet(observable), IObservableSet.class);
+ }
+
+ return result;
+ }
+
+ public static IObservableSet create(Realm realm, ClassLoader loader, Class<?>... mixins) {
+ return DelegatingInvocationHandler.wrap(new DelegatingObservableSet(realm), IObservableSet.class, loader, mixins);
+ }
+
+ public void addSetChangeListener(ISetChangeListener listener) {
+ addListener(SET_EVENT_TYPE, listener);
+ }
+
+ public void removeSetChangeListener(ISetChangeListener listener) {
+ removeListener(SET_EVENT_TYPE, listener);
+ }
+
+ @Override
+ protected void hookDelegate(IObservableSet delegate) {
+ super.hookDelegate(delegate);
+ delegate.addSetChangeListener(getForwardingSetChangeListener());
+ }
+
+ @Override
+ protected void unhookDelegate(IObservableSet delegate) {
+ delegate.removeSetChangeListener(getForwardingSetChangeListener());
+ super.unhookDelegate(delegate);
+ }
+
+ @Override
+ protected void delegateChanged(IObservableSet oldDelegate, IObservableSet newDelegate) {
+ super.delegateChanged(oldDelegate, newDelegate);
+
+ Set<?> oldSet = ((oldDelegate == null) || oldDelegate.isDisposed()) ? Collections.EMPTY_SET : oldDelegate;
+ Set<?> newSet = (newDelegate == null) ? Collections.EMPTY_SET : newDelegate;
+
+ fireEvent(new MySetChangeEvent(Diffs.computeSetDiff(oldSet, newSet)));
+ }
+
+ private ISetChangeListener getForwardingSetChangeListener() {
+ if(forwardingSetChangeListener == null) {
+ forwardingSetChangeListener = new ISetChangeListener() {
+
+ public void handleSetChange(SetChangeEvent event) {
+ SetChangeEvent myEvent = new MySetChangeEvent(event.diff);
+ fireEvent(myEvent);
+ }
+ };
+ }
+
+ return forwardingSetChangeListener;
+ }
+
+ //
+ // Nested types
+ //
+
+ class MySetChangeEvent extends SetChangeEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ MySetChangeEvent(SetDiff diff) {
+ super(getRealObservable(), diff);
+ }
+
+ @Override
+ protected Object getListenerType() {
+ // We implement our own listener type because the type from the core framework is not accessible
+ return SET_EVENT_TYPE;
+ }
+ }
+
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableValue.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableValue.java
new file mode 100644
index 00000000000..6c75786a1aa
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/DelegatingObservableValue.java
@@ -0,0 +1,140 @@
+/*
+ * 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.tools.databinding;
+
+import org.eclipse.core.databinding.observable.Diffs;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.observable.value.IValueChangeListener;
+import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
+import org.eclipse.core.databinding.observable.value.ValueDiff;
+
+
+/**
+ * This is the DelegatingObservableValue type. Enjoy.
+ */
+public class DelegatingObservableValue extends DelegatingObservable<IObservableValue> implements IObservableValue {
+
+ private static final Object VALUE_EVENT_TYPE = new Object();
+
+ private IValueChangeListener forwardingValueChangeListener;
+
+ DelegatingObservableValue(IObservableValue delegate) {
+ super(delegate, IObservableValue.class);
+ }
+
+ DelegatingObservableValue(Realm realm) {
+ super(realm, IObservableValue.class);
+ }
+
+ public static IObservableValue wrap(IObservableValue observable) {
+ IObservableValue result;
+
+ if(observable instanceof IDelegatingObservable) {
+ // Already have a delegator. Just create another like it
+ try {
+ result = (IObservableValue)observable.getClass().getDeclaredConstructor(IObservableValue.class).newInstance(observable);
+ } catch (Exception e) {
+ // Seems unlikely as I must have created the observable in the first place
+ throw new IllegalArgumentException("observable is an invalid implementation of IDelegatingObservable", e); //$NON-NLS-1$
+ }
+ } else {
+ result = DelegatingInvocationHandler.wrap(new DelegatingObservableValue(observable), IObservableValue.class);
+ }
+
+ return result;
+ }
+
+ public static IObservableValue create(Realm realm, ClassLoader loader, Class<?>... mixins) {
+ return DelegatingInvocationHandler.wrap(new DelegatingObservableValue(realm), IObservableValue.class, loader, mixins);
+ }
+
+ public void addValueChangeListener(IValueChangeListener listener) {
+ addListener(VALUE_EVENT_TYPE, listener);
+ }
+
+ public void removeValueChangeListener(IValueChangeListener listener) {
+ removeListener(VALUE_EVENT_TYPE, listener);
+ }
+
+ @Override
+ protected void hookDelegate(IObservableValue delegate) {
+ super.hookDelegate(delegate);
+ delegate.addValueChangeListener(getForwardingValueChangeListener());
+ }
+
+ @Override
+ protected void unhookDelegate(IObservableValue delegate) {
+ delegate.removeValueChangeListener(getForwardingValueChangeListener());
+ super.unhookDelegate(delegate);
+ }
+
+ @Override
+ protected void delegateChanged(IObservableValue oldDelegate, IObservableValue newDelegate) {
+ super.delegateChanged(oldDelegate, newDelegate);
+
+ Object oldValue = ((oldDelegate == null) || oldDelegate.isDisposed()) ? null : oldDelegate.getValue();
+ Object newValue = (newDelegate == null) ? null : newDelegate.getValue();
+
+ fireEvent(new MyValueChangeEvent(Diffs.createValueDiff(oldValue, newValue)));
+ }
+
+ public Object getValueType() {
+ return (getDelegate() == null) ? Void.class : getDelegate().getValueType();
+ }
+
+ public Object getValue() {
+ getterCalled();
+
+ return (getDelegate() == null) ? null : getDelegate().getValue();
+ }
+
+ public void setValue(Object value) {
+ if(getDelegate() != null) {
+ getDelegate().setValue(value);
+ }
+ }
+
+ private IValueChangeListener getForwardingValueChangeListener() {
+ if(forwardingValueChangeListener == null) {
+ forwardingValueChangeListener = new IValueChangeListener() {
+
+ public void handleValueChange(ValueChangeEvent event) {
+ ValueChangeEvent myEvent = new MyValueChangeEvent(event.diff);
+ fireEvent(myEvent);
+ }
+ };
+ }
+
+ return forwardingValueChangeListener;
+ }
+
+ //
+ // Nested types
+ //
+
+ class MyValueChangeEvent extends ValueChangeEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ MyValueChangeEvent(ValueDiff diff) {
+ super(getRealObservable(), diff);
+ }
+
+ @Override
+ protected Object getListenerType() {
+ // We implement our own listener type because the type from the core framework is not accessible
+ return VALUE_EVENT_TYPE;
+ }
+ }
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/IDelegatingObservable.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/IDelegatingObservable.java
new file mode 100644
index 00000000000..2fa0e07bc86
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/IDelegatingObservable.java
@@ -0,0 +1,53 @@
+/*
+ * 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.tools.databinding;
+
+import org.eclipse.core.databinding.observable.IObservable;
+
+
+
+/**
+ * <p>
+ * An {@linkplain IObservable observable} that delegates its function (including notification of state changes) to a wrapped instance. The delegate
+ * may be {@linkplain #setDelegate(IObservable) replaced} at any time. Thus, the lifecycle of a delegator is independent of its delegate and
+ * {@link #dispose() disposing} a delegator only disposes it, not its delegate if it has one at the time.
+ * </p>
+ * <p>
+ * Delegating observables may be created via factory methods provided by the {@link DelegatingObservable} class.
+ * </p>
+ *
+ * @see DelegatingObservable
+ */
+public interface IDelegatingObservable extends IObservable, ReferenceCountedObservable {
+
+ /**
+ * Assigns me a new delegate, or at least forgets my delegate if {@code null}.
+ *
+ * @param delegate
+ * my delegate (may be {@code null})
+ */
+ void setDelegate(IObservable delegate);
+
+ /**
+ * Obtains my current delegate, if any.
+ *
+ * @return my delegate, or {@code null} if I have none
+ */
+ IObservable getDelegate();
+
+ /**
+ * Disposes of me and my own resources only. In particular, if I have a {@linkplain #getDelegate() delegate}, it is <em>not</em> disposed, but
+ * must be disposed independently.
+ */
+ void dispose();
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/MultipleObservableValue.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/MultipleObservableValue.java
index bd8dadf1e11..a326d80dab1 100644
--- a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/MultipleObservableValue.java
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/MultipleObservableValue.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.tools.databinding;
@@ -18,7 +20,6 @@ import java.util.List;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
-import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.ValueDiff;
@@ -32,7 +33,7 @@ import org.eclipse.core.databinding.observable.value.ValueDiff;
* All sub-elements will be edited at the same time, with the same value.
*/
//TODO : Add listeners on sub-observables, and remove them on dispose
-public class MultipleObservableValue extends AbstractObservableValue implements AggregatedObservable, IChangeListener {
+public class MultipleObservableValue extends ReferenceCountedObservable.Value implements AggregatedObservable, IChangeListener {
/**
*
@@ -98,6 +99,7 @@ public class MultipleObservableValue extends AbstractObservableValue implements
public AggregatedObservable aggregate(IObservable observable) {
if(observable instanceof IObservableValue) {
+ ReferenceCountedObservable.Util.retain(observable);
observableValues.add((IObservableValue)observable);
observable.addChangeListener(this);
return this;
@@ -128,8 +130,12 @@ public class MultipleObservableValue extends AbstractObservableValue implements
super.dispose();
for(IObservableValue observable : observableValues) {
observable.removeChangeListener(this);
- observable.dispose();
+
+ // I don't own my observables, so I just release them
+ ReferenceCountedObservable.Util.release(observable);
}
+
+ observableValues.clear();
}
/**
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/ReferenceCountedObservable.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/ReferenceCountedObservable.java
new file mode 100644
index 00000000000..41a9ebf5ee9
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/databinding/ReferenceCountedObservable.java
@@ -0,0 +1,372 @@
+/*
+ * 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.tools.databinding;
+
+import java.lang.ref.WeakReference;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.core.databinding.observable.AbstractObservable;
+import org.eclipse.core.databinding.observable.DisposeEvent;
+import org.eclipse.core.databinding.observable.IDisposeListener;
+import org.eclipse.core.databinding.observable.IObservable;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.MapMaker;
+
+
+
+/**
+ * A mix-in interface for {@link IObservable}s that support reference counting as a means to automatically dispose of them while ensuring that
+ * they may be freely shared without any client finding itself interacting with a disposed observable.
+ */
+public interface ReferenceCountedObservable extends IObservable {
+
+ /**
+ * Retains me for use by the caller, which should be sure to {@linkplain #release() release me} when I am no longer needed.
+ * As long as I have been retained by at least one client, I shall not {@linkplain IObservable#dispose() dispose} myself.
+ *
+ * @see #release()
+ */
+ void retain();
+
+ /**
+ * Releases me, indicating that I am no longer being used by the caller. When my {@linkplain #retain() retain count} reaches zero,
+ * I automatically {@linkplain IObservable#dispose() dispose} myself, because no client needs me.
+ *
+ * @see #retain()
+ * @see #autorelease()
+ * @see IObservable#dispose()
+ */
+ void release();
+
+ /**
+ * Automatically releases me some time after the current iteration of the UI event loop. This is useful when it is
+ * expected that the UI will still need to be able to access the observable for refreshes while processing the
+ * current event.
+ *
+ * @see #release()
+ */
+ void autorelease();
+
+ /**
+ * A composable assistant to implement the {@link ReferenceCountedObservable} protocol by delegating of its API.
+ */
+ class Support {
+
+ private final IObservable observable;
+
+ private final AtomicInteger refCount = new AtomicInteger();
+
+ /**
+ * Creates a new instance to support reference counting on behalf of an {@code observable}.
+ *
+ * @param observable
+ * the observable for which to provide reference counting
+ */
+ public Support(IObservable observable) {
+ this.observable = observable;
+ }
+
+ public void retain() {
+ refCount.incrementAndGet();
+ }
+
+ public void release() {
+ if((refCount.decrementAndGet() <= 0) && !observable.isDisposed()) {
+ observable.dispose();
+ }
+ }
+
+ public void autorelease() {
+ AutoReleasePool.get(observable.getRealm()).add(observable);
+ }
+ }
+
+ /**
+ * A convenient superclass for reference-counted observables that don't need any other more specific superclass.
+ */
+ abstract class Abstract extends AbstractObservable implements ReferenceCountedObservable {
+
+ private final Support refCount = new Support(this);
+
+ public Abstract(Realm realm) {
+ super(realm);
+ }
+
+ public void retain() {
+ refCount.retain();
+ }
+
+ public void release() {
+ refCount.release();
+ }
+
+ public void autorelease() {
+ refCount.autorelease();
+ }
+ }
+
+ /**
+ * A convenient superclass for reference-counted observable values that don't need any other more specific superclass.
+ */
+ abstract class Value extends AbstractObservableValue implements ReferenceCountedObservable {
+
+ private final Support refCount = new Support(this);
+
+ public Value() {
+ super();
+ }
+
+ public Value(Realm realm) {
+ super(realm);
+ }
+
+ public void retain() {
+ refCount.retain();
+ }
+
+ public void release() {
+ refCount.release();
+ }
+
+ public void autorelease() {
+ refCount.autorelease();
+ }
+ }
+
+ /**
+ * A pool of {@link IObservable}s to be released automatically after the completion of the current iteration
+ * of the UI event loop (or whatever determines the asynchronous execution of tasks in a given {@link Realm}).
+ */
+ final class AutoReleasePool {
+
+ private static final ConcurrentMap<Realm, AutoReleasePool> pools = new MapMaker().concurrencyLevel(1).makeMap();
+
+ private final Realm realm;
+
+ private Collection<IObservable> pool = Lists.newArrayList();
+
+ private AutoReleasePool(Realm realm) {
+ this.realm = realm;
+
+ realm.asyncExec(new ReleaseRunnable());
+ }
+
+ public static AutoReleasePool get(Realm realm) {
+ AutoReleasePool result = pools.get(realm);
+ if(result == null) {
+ result = new AutoReleasePool(realm);
+
+ // Double-check
+ AutoReleasePool oops = pools.putIfAbsent(realm, result);
+ if(oops != null) {
+ result = oops;
+ }
+ }
+
+ return result;
+ }
+
+ public synchronized void add(IObservable observable) {
+ if(pool == null) {
+ pool = Lists.newArrayList();
+ }
+
+ pool.add(observable);
+ }
+
+ public void release() {
+ pools.remove(realm);
+
+ for(;;) {
+ Iterable<IObservable> toDrain;
+
+ synchronized(this) {
+ toDrain = pool;
+ pool = null;
+ }
+
+ if(toDrain != null) {
+ // Drain this pool
+ for(IObservable next : toDrain) {
+ Util.release(next);
+ }
+ } else {
+ // Done. No more pools to drain
+ break;
+ }
+ }
+ }
+
+ private final class ReleaseRunnable implements Runnable {
+
+ public void run() {
+ release();
+ }
+ }
+ }
+
+ /**
+ * Utility APIs for working with reference-counted observables. In particular, this provides external reference-counting
+ * for observables that don't implement it internally via the {@link ReferenceCountedObservable} protocol.
+ */
+ final class Util {
+
+ // Use the Guava weak map because that uses object identity for comparisons, which is critical
+ // to avoid using equals() which will often fail on an assertion violation for accessing a
+ // getter of a disposed observable
+ private static final Map<IObservable, WeakRefCount> adapters = new MapMaker().concurrencyLevel(1).weakKeys().makeMap();
+
+ private Util() {
+ super();
+ }
+
+ /**
+ * Provides a unified interface to retaining observables, delegating to the {@link ReferenceCountedObservable} protocol
+ * for observables that implement it, otherwise providing an external reference-count (which is GC-safe).
+ *
+ * @param observable
+ * an observable to retain
+ *
+ * @return the same {@code observable} (useful for call chaining)
+ *
+ * @see ReferenceCountedObservable#retain()
+ */
+ public static <T extends IObservable> T retain(T observable) {
+ if(observable instanceof ReferenceCountedObservable) {
+ ((ReferenceCountedObservable)observable).retain();
+ } else if(!observable.isDisposed()) { // Don't bother counting if already disposed
+ WeakRefCount adapter = adapt(observable, true);
+ adapter.retain();
+ }
+
+ return observable;
+ }
+
+ /**
+ * Provides a unified interface to releasing observables, delegating to the {@link ReferenceCountedObservable} protocol
+ * for observables that implement it, otherwise providing an external reference-count (which is GC-safe). Note that
+ * for externally reference-counted observables, they are automatically disposed as usual when the retain count drops
+ * to zero, just as though they implemented reference counting internally.
+ *
+ * @param observable
+ * an observable to release. If its retain count is zero as a result (whether intrinsic or extrinsic), it will be disposed
+ *
+ * @return the same {@code observable} (useful for call chaining)
+ *
+ * @see ReferenceCountedObservable#release()
+ */
+ public static <T extends IObservable> T release(T observable) {
+ if(observable instanceof ReferenceCountedObservable) {
+ ((ReferenceCountedObservable)observable).release();
+ } else if(!observable.isDisposed()) { // Don't bother counting if already disposed
+ WeakRefCount adapter = adapt(observable, false);
+
+ // There won't be an adapter if there was no prior retain (of course) or if it was already disposed
+ if(adapter != null) {
+ adapter.release();
+ }
+ }
+
+ return observable;
+ }
+
+ /**
+ * Provides a unified interface to auto-releasing observables, delegating to the {@link ReferenceCountedObservable} protocol
+ * for observables that implement it, otherwise providing an external reference-count (which is GC-safe). Note that
+ * for externally reference-counted observables, they are automatically disposed as usual when the retain count drops
+ * to zero, just as though they implemented reference counting internally.
+ *
+ * @param observable
+ * an observable to release. If its retain count is zero as a result (whether intrinsic or extrinsic), it will be disposed
+ *
+ * @return the same {@code observable} (useful for call chaining)
+ *
+ * @see ReferenceCountedObservable#autorelease()
+ */
+ public static <T extends IObservable> T autorelease(T observable) {
+ if(observable instanceof ReferenceCountedObservable) {
+ ((ReferenceCountedObservable)observable).autorelease();
+ } else if(!observable.isDisposed()) { // Don't bother counting if already disposed
+ WeakRefCount adapter = adapt(observable, false);
+
+ // There won't be an adapter if there was no prior retain (of course) or if it was already disposed
+ if(adapter != null) {
+ adapter.autorelease();
+ }
+ }
+
+ return observable;
+ }
+
+ private static WeakRefCount adapt(IObservable observable, boolean create) {
+ WeakRefCount result = adapters.get(observable);
+
+ if((result == null) && create) {
+ result = new WeakRefCount(observable);
+ adapters.put(observable, result);
+ }
+
+ return result;
+ }
+
+ private static final class WeakRefCount extends WeakReference<IObservable> implements IDisposeListener {
+
+ private final AtomicInteger refCount = new AtomicInteger();
+
+ WeakRefCount(IObservable observable) {
+ super(observable);
+
+ observable.addDisposeListener(this);
+ }
+
+ public void retain() {
+ refCount.incrementAndGet();
+ }
+
+ public void release() {
+ if(refCount.decrementAndGet() <= 0) {
+ IObservable observable = get();
+
+ if(observable != null) {
+ if(!observable.isDisposed()) {
+ observable.dispose();
+ }
+
+ clear();
+ }
+ }
+ }
+
+ public void autorelease() {
+ IObservable observable = get();
+
+ // If it's null, then it's already disposed, so auto-release is meaningless
+ if(observable != null) {
+ AutoReleasePool.get(observable.getRealm()).add(observable);
+ }
+ }
+
+ public void handleDispose(DisposeEvent event) {
+ if(event.getObservable() == get()) {
+ clear();
+ }
+ }
+ }
+ }
+}
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 f99ed5ba9a9..f7249f3146c 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
@@ -11,6 +11,7 @@
* Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation
* Christian W. Damus (CEA) - bug 402525
* Mickaƫl ADAM (ALL4TEC) mickael.adam@all4tec.net - bug 435415
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
@@ -217,13 +218,19 @@ public abstract class AbstractValueEditor extends AbstractEditor {
@Override
public void handleValueChange(ValueChangeEvent event) {
- //Check if the widget is disposed before isReadOnly() to avoid NPE
- if(!AbstractValueEditor.this.isDisposed() && !isReadOnly()) { //Bug 434787 : Shouldn't not execute the timer thread if the widget is disposed
- IStatus status = (IStatus)binding.getValidationStatus().getValue(); //Bug 435415 : Update the status only if the widget isn't disposed
- updateStatus(status);
- changeColorField();
+ // Don't handle validation changes if we don't have a validator, because then it could only be green and it isn't useful.
+ // Also, if we're showing in a dialog, then our widget may have been disposed already if we're validating a change applied
+ // by hitting the OK button
+ if((modelValidator) != null) {
+ //Check if the widget is disposed before isReadOnly() to avoid NPE
+ if(!AbstractValueEditor.this.isDisposed() && !isReadOnly()) { //Bug 434787 : Shouldn't not execute the timer thread if the widget is disposed
+ IStatus status = (IStatus)binding.getValidationStatus().getValue(); //Bug 435415 : Update the status only if the widget isn't disposed
+ updateStatus(status);
+ changeColorField();
+ }
}
}
+
});
}
@@ -248,11 +255,9 @@ public abstract class AbstractValueEditor extends AbstractEditor {
* @param modelValidator
*/
public void setModelValidator(IValidator targetToModelValidator) {
- if(targetToModelValidator != null) {
this.modelValidator = targetToModelValidator;
targetToModelStrategy.setBeforeSetValidator(targetToModelValidator);
modelToTargetStrategy.setAfterGetValidator(targetToModelValidator);
- }
}
/**
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/BehaviorDisplayHelper.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/BehaviorDisplayHelper.java
index 5e35abe5b4c..91063f64d34 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/BehaviorDisplayHelper.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/BehaviorDisplayHelper.java
@@ -1,7 +1,6 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA
+ * 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
@@ -9,6 +8,7 @@
*
* Contributors:
* Soyatec - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;
@@ -34,27 +34,17 @@ import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElementFactory;
/**
* @author Jin Liu (jin.liu@soyatec.com)
*/
-public class BehaviorDisplayHelper implements ModelElementFactory {
+public class BehaviorDisplayHelper extends AnnotationModelElementFactory {
private static final String DISPLAY_BEHAVIOR = "displayBehavior";
- /**
- * @see org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory#createFromSource(java.lang.Object,
- * org.eclipse.papyrus.views.properties.contexts.DataContextElement)
- *
- * @param sourceElement
- * @param context
- * @return
- */
-
- public ModelElement createFromSource(Object sourceElement,
- DataContextElement context) {
+ @Override
+ protected AnnotationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View source = NotationHelper.findView(sourceElement);
if (source == null) {
Activator.log
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/GateModelElementFactory.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/GateModelElementFactory.java
index 35db9fe7361..0c9f1c21a43 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/GateModelElementFactory.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/GateModelElementFactory.java
@@ -1,6 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA
- *
+ * 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
@@ -9,6 +8,7 @@
*
* Contributors:
* Soyatec - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;
@@ -27,25 +27,17 @@ import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElementFactory;
/**
* @author Jin Liu (jin.liu@soyatec.com)
*/
-public class GateModelElementFactory implements ModelElementFactory {
+public class GateModelElementFactory extends AnnotationModelElementFactory {
private static final String GATE_SHOW_NAME = "showName";
- /**
- * @see org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory#createFromSource(java.lang.Object,
- * org.eclipse.papyrus.views.properties.contexts.DataContextElement)
- *
- * @param sourceElement
- * @param context
- * @return
- */
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected AnnotationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View source = NotationHelper.findView(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/InteractionOperandModelElementFactory.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/InteractionOperandModelElementFactory.java
index 4d2e6dda83a..c5b9df45aac 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/InteractionOperandModelElementFactory.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/InteractionOperandModelElementFactory.java
@@ -1,7 +1,6 @@
/*****************************************************************************
- * Copyright (c) 2010 CEA
- *
- *
+ * 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
@@ -9,6 +8,8 @@
*
* Contributors:
* Soyatec - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;
@@ -29,8 +30,7 @@ import org.eclipse.papyrus.uml.diagram.sequence.preferences.CustomInteractionOpe
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElementFactory;
/**
* Add the possibility to display or hide the guard of Operand
@@ -39,19 +39,12 @@ import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
*
* @author Jin Liu (jin.liu@soyatec.com)
*/
-public class InteractionOperandModelElementFactory implements ModelElementFactory {
+public class InteractionOperandModelElementFactory extends AnnotationModelElementFactory {
public static final String GUARD_VISIBILITY_KEY = "guard.visibility";
- /**
- * @see org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory#createFromSource(java.lang.Object,
- * org.eclipse.papyrus.views.properties.contexts.DataContextElement)
- *
- * @param sourceElement
- * @param context
- * @return
- */
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected AnnotationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View source = NotationHelper.findView(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/LinkRouteModelElementFactory.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/LinkRouteModelElementFactory.java
index b93042e29e0..e083a906ea5 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/LinkRouteModelElementFactory.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/LinkRouteModelElementFactory.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA
+ * Copyright (c) 2013, 2014 CEA and others
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@
*
* Contributors:
* Soyatec - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;
@@ -36,10 +37,9 @@ import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AnnotationModelElementFactory;
-public class LinkRouteModelElementFactory implements ModelElementFactory {
+public class LinkRouteModelElementFactory extends AnnotationModelElementFactory {
public static final String STYLE = "style";
@@ -51,7 +51,8 @@ public class LinkRouteModelElementFactory implements ModelElementFactory {
public static final Map<Object, LinkRouteModelElement> elements = new HashMap<Object, LinkRouteModelElement>();
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected AnnotationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View view = NotationHelper.findView(sourceElement);
if(view != null && view instanceof Edge) {
EditingDomain domain = EMFHelper.resolveEditingDomain(view);
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/MessageStyleElementFactory.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/MessageStyleElementFactory.java
index c4ee9ded95f..35893c76684 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/MessageStyleElementFactory.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/MessageStyleElementFactory.java
@@ -1,3 +1,16 @@
+/*****************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
+ *****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;
import org.eclipse.core.databinding.observable.IObservable;
@@ -12,24 +25,33 @@ import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.uml.tools.databinding.PapyrusObservableValue;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
-public class MessageStyleElementFactory implements ModelElementFactory {
+public class MessageStyleElementFactory extends AbstractModelElementFactory<MessageStyleElementFactory.MessageStyleModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected MessageStyleModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
View view = NotationHelper.findView(sourceElement);
if(view != null && view instanceof Edge) {
return new MessageStyleModelElement((Edge)view, context);
}
return null;
}
+
+ @Override
+ protected void updateModelElement(MessageStyleModelElement modelElement, Object newSourceElement) {
+ View view = NotationHelper.findView(newSourceElement);
+ if(!(view instanceof Edge)) {
+ throw new IllegalArgumentException("Cannot resolve Edge selection: " + newSourceElement);
+ }
+ modelElement.source = (Edge)view;
+ }
static class MessageStyleModelElement extends AbstractModelElement {
protected DataContextElement context;
- private Edge source;
+ protected Edge source;
public MessageStyleModelElement(Edge source, DataContextElement context) {
this.context = context;
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/PreferencesModelElementFactory.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/PreferencesModelElementFactory.java
index 77b9f96fad9..6de72de94a0 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/PreferencesModelElementFactory.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/PreferencesModelElementFactory.java
@@ -1,13 +1,20 @@
+/*****************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
+ *****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;
-import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
-import org.eclipse.papyrus.views.properties.modelelement.PreferencesModelElement;
-public class PreferencesModelElementFactory implements ModelElementFactory {
+public class PreferencesModelElementFactory extends org.eclipse.papyrus.views.properties.modelelement.PreferencesModelElementFactory {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
- return new PreferencesModelElement(context);
- }
+ // Empty
}
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CommentModelElementFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CommentModelElementFactory.java
index 5c0d6c429b2..a8de726dc5a 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CommentModelElementFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CommentModelElementFactory.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:
* Sebastien Poissonnet (CEA LIST) sebastien.poissonnet@cea.fr
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -16,13 +18,13 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractEMFModelElementFactory;
import org.eclipse.uml2.uml.Element;
-public class CommentModelElementFactory implements ModelElementFactory {
+public class CommentModelElementFactory extends AbstractEMFModelElementFactory<CommentModelElement> {
- public ModelElement createFromSource(Object source, DataContextElement context) {
+ @Override
+ protected CommentModelElement doCreateFromSource(Object source, DataContextElement context) {
Element umlSource = UMLUtil.resolveUMLElement(source);
if(umlSource == null) {
Activator.log.warn("Unable to resolve the selected element to a UML Element"); //$NON-NLS-1$
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CustomImageModelElementFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CustomImageModelElementFactory.java
index 11f4eb409de..eb8c6cf40bd 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CustomImageModelElementFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/CustomImageModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -16,8 +18,7 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.properties.Activator;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Image;
@@ -27,9 +28,10 @@ import org.eclipse.uml2.uml.Image;
* @author Camille Letavernier
*
*/
-public class CustomImageModelElementFactory implements ModelElementFactory {
+public class CustomImageModelElementFactory extends AbstractModelElementFactory<CustomImageModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected CustomImageModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
Element umlSource = UMLUtil.resolveUMLElement(sourceElement);
if(umlSource == null) {
Activator.log.warn("Unable to resolve the selected element to a UML Element"); //$NON-NLS-1$
@@ -45,4 +47,13 @@ public class CustomImageModelElementFactory implements ModelElementFactory {
return null;
}
+ @Override
+ protected void updateModelElement(CustomImageModelElement modelElement, Object newSourceElement) {
+ Element element = UMLUtil.resolveUMLElement(newSourceElement);
+ if(!(element instanceof Image)) {
+ throw new IllegalArgumentException("Cannot resolve UML Image selection: " + newSourceElement);
+ }
+ modelElement.image = (Image)element;
+ modelElement.editingDomain = EMFHelper.resolveEditingDomain(element);
+ }
}
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/MemberEndModelElement.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/MemberEndModelElement.java
index 326e894de72..d10b6c090f2 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/MemberEndModelElement.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/MemberEndModelElement.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -45,9 +46,9 @@ import org.eclipse.uml2.uml.UMLPackage;
*/
public class MemberEndModelElement extends AbstractModelElement {
- private EObject source;
+ protected EObject source;
- private EditingDomain domain;
+ protected EditingDomain domain;
/**
* The "multiplicity" virtual property
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/ProfileDefinitionModelElementFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/ProfileDefinitionModelElementFactory.java
index ed2226ab56e..5e0917db1f0 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/ProfileDefinitionModelElementFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/ProfileDefinitionModelElementFactory.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
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,21 +8,23 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Profile;
-public class ProfileDefinitionModelElementFactory implements ModelElementFactory {
+public class ProfileDefinitionModelElementFactory extends AbstractModelElementFactory<ProfileDefinitionModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected ProfileDefinitionModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
Element umlSource = UMLUtil.resolveUMLElement(sourceElement);
if(umlSource instanceof Profile) {
//EditingDomain domain = EMFHelper.resolveEditingDomain(umlSource);
@@ -33,4 +35,12 @@ public class ProfileDefinitionModelElementFactory implements ModelElementFactory
return null;
}
+ @Override
+ protected void updateModelElement(ProfileDefinitionModelElement modelElement, Object newSourceElement) {
+ Element element = org.eclipse.papyrus.uml.tools.utils.UMLUtil.resolveUMLElement(newSourceElement);
+ if(!(element instanceof Profile)) {
+ throw new IllegalArgumentException("Cannot resolve UML Profile selection: " + newSourceElement);
+ }
+ modelElement.profile = (Profile)element;
+ }
}
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceFactory.java
index 815c2f19be6..588a3d899e0 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -18,8 +20,7 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
import org.eclipse.uml2.uml.Element;
/**
@@ -28,9 +29,10 @@ import org.eclipse.uml2.uml.Element;
* @author Camille Letavernier
*
*/
-public class StereotypeAppearanceFactory implements ModelElementFactory {
+public class StereotypeAppearanceFactory extends AbstractModelElementFactory<StereotypeAppearanceModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected StereotypeAppearanceModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
Element umlSource = UMLUtil.resolveUMLElement(sourceElement);
if(umlSource == null) {
@@ -48,4 +50,15 @@ public class StereotypeAppearanceFactory implements ModelElementFactory {
return null;
}
+ @Override
+ protected void updateModelElement(StereotypeAppearanceModelElement modelElement, Object newSourceElement) {
+ if(!(newSourceElement instanceof EditPart)) {
+ throw new IllegalArgumentException("Cannot resolve EditPart selection: " + newSourceElement);
+ }
+
+ Element umlSource = UMLUtil.resolveUMLElement(newSourceElement);
+ modelElement.umlSource = umlSource;
+ modelElement.diagramElement = (EModelElement)((EditPart)newSourceElement).getModel();
+ modelElement.domain = EMFHelper.resolveEditingDomain(umlSource);
+ }
}
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceModelElement.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceModelElement.java
index 033b0071f2b..53612a08ae8 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceModelElement.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeAppearanceModelElement.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -36,7 +37,6 @@ import org.eclipse.papyrus.infra.widgets.providers.StaticContentProvider;
import org.eclipse.papyrus.uml.properties.Activator;
import org.eclipse.papyrus.uml.properties.databinding.StereotypeAppearanceObservableValue;
import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
import org.eclipse.uml2.uml.Element;
/**
@@ -48,7 +48,7 @@ import org.eclipse.uml2.uml.Element;
* @author Camille Letavernier
*
*/
-public class StereotypeAppearanceModelElement extends AbstractModelElement implements ModelElement {
+public class StereotypeAppearanceModelElement extends AbstractModelElement {
/**
* The current UML Element
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationFactory.java
index b9720d0b759..c1d89b32dd7 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -17,8 +19,7 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractEMFModelElementFactory;
import org.eclipse.uml2.uml.Element;
/**
@@ -28,9 +29,10 @@ import org.eclipse.uml2.uml.Element;
* @author Camille Letavernier
*
*/
-public class StereotypeApplicationFactory implements ModelElementFactory {
+public class StereotypeApplicationFactory extends AbstractEMFModelElementFactory<StereotypeApplicationModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected StereotypeApplicationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
Element umlSource = UMLUtil.resolveUMLElement(sourceElement);
if(umlSource == null) {
Activator.log.warn("Unable to resolve the selected element to a UML Element"); //$NON-NLS-1$
@@ -45,4 +47,16 @@ public class StereotypeApplicationFactory implements ModelElementFactory {
}
}
+ @Override
+ protected void updateModelElement(StereotypeApplicationModelElement modelElement, Object newSourceElement) {
+ Element element = UMLUtil.resolveUMLElement(newSourceElement);
+ if(element == null) {
+ throw new IllegalArgumentException("Cannot resolve UML element selection: " + newSourceElement);
+ }
+ modelElement.umlSource = element;
+ modelElement.domain = EMFHelper.resolveEditingDomain(element);
+ modelElement.sourceElement = (newSourceElement instanceof EditPart) ? (EditPart)newSourceElement : null;
+
+ super.updateModelElement(modelElement, newSourceElement);
+ }
}
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationModelElement.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationModelElement.java
index 814a1519a5a..2ff1bf70958 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationModelElement.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeApplicationModelElement.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -41,11 +43,11 @@ import org.eclipse.uml2.uml.UMLPackage;
*/
public class StereotypeApplicationModelElement extends EMFModelElement {
- private Element umlSource;
+ protected Element umlSource;
- private EditingDomain domain;
+ protected EditingDomain domain;
- private EditPart sourceElement;
+ protected EditPart sourceElement;
/**
* The "stereotypeApplication" pseudo-property for a UML Element
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeModelElementFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeModelElementFactory.java
index 9a53ab7eaf6..fd4cde0488e 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeModelElementFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/StereotypeModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -17,8 +19,8 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.properties.Activator;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.EMFModelElement;
+import org.eclipse.papyrus.views.properties.modelelement.EMFModelElementFactory;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Stereotype;
@@ -41,9 +43,10 @@ import org.eclipse.uml2.uml.Stereotype;
*
* @author Camille Letavernier
*/
-public class StereotypeModelElementFactory implements ModelElementFactory {
+public class StereotypeModelElementFactory extends EMFModelElementFactory {
- public ModelElement createFromSource(Object source, DataContextElement context) {
+ @Override
+ protected EMFModelElement doCreateFromSource(Object source, DataContextElement context) {
Element umlElement = UMLUtil.resolveUMLElement(source);
if(umlElement != null) {
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLEditorFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLEditorFactory.java
index 4416258fe15..ef56f526563 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLEditorFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLEditorFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -16,8 +18,7 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
/**
* A Factory for building ModelElements for specific UML properties
@@ -25,9 +26,10 @@ import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
*
* @author Camille Letavernier
*/
-public class UMLEditorFactory implements ModelElementFactory {
+public class UMLEditorFactory extends AbstractModelElementFactory<MemberEndModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected MemberEndModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$
@@ -39,4 +41,13 @@ public class UMLEditorFactory implements ModelElementFactory {
return new MemberEndModelElement(source, domain);
}
+ @Override
+ protected void updateModelElement(MemberEndModelElement modelElement, Object newSourceElement) {
+ EObject eObject = EMFHelper.getEObject(newSourceElement);
+ if(eObject == null) {
+ throw new IllegalArgumentException("Cannot resolve EObject selection: " + newSourceElement);
+ }
+ modelElement.source = eObject;
+ modelElement.domain = EMFHelper.resolveEditingDomain(eObject);
+ }
}
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLModelElementFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLModelElementFactory.java
index 38fff4b2838..fb909dd50bf 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLModelElementFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -16,8 +18,7 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.EMFModelElementFactory;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractEMFModelElementFactory;
import org.eclipse.uml2.uml.Element;
/**
@@ -25,10 +26,10 @@ import org.eclipse.uml2.uml.Element;
*
* @author Camille Letavernier
*/
-public class UMLModelElementFactory extends EMFModelElementFactory {
+public class UMLModelElementFactory extends AbstractEMFModelElementFactory<UMLModelElement> {
@Override
- public ModelElement createFromSource(Object source, DataContextElement context) {
+ protected UMLModelElement doCreateFromSource(Object source, DataContextElement context) {
Element umlSource = UMLUtil.resolveUMLElement(source);
if(umlSource == null) {
Activator.log.warn("Unable to resolve the selected element to a UML Element"); //$NON-NLS-1$
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationFactory.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationFactory.java
index 8bc23caf53e..a1ba5c2c92c 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationFactory.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationFactory.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,14 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
import org.eclipse.gef.EditPart;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
-import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
+import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElementFactory;
/**
* A ModelElementFactory for handling UML-specific appearance properties
@@ -22,13 +23,21 @@ import org.eclipse.papyrus.views.properties.modelelement.ModelElementFactory;
* @author Camille Letavernier
*
*/
-public class UMLNotationFactory implements ModelElementFactory {
+public class UMLNotationFactory extends AbstractModelElementFactory<UMLNotationModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected UMLNotationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
if(sourceElement instanceof EditPart) {
return new UMLNotationModelElement((EditPart)sourceElement);
}
return null;
}
+ @Override
+ protected void updateModelElement(UMLNotationModelElement modelElement, Object newSourceElement) {
+ if(!(newSourceElement instanceof EditPart)) {
+ throw new IllegalArgumentException("Cannot resolve EditPart selection: " + newSourceElement);
+ }
+ modelElement.sourceElement = (EditPart)newSourceElement;
+ }
}
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationModelElement.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationModelElement.java
index c6c680cd2d8..e72a6ce32d2 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationModelElement.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/modelelement/UMLNotationModelElement.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.modelelement;
@@ -68,7 +69,7 @@ public class UMLNotationModelElement extends AbstractModelElement {
/**
* The GMF EditPart represented by this ModelElement
*/
- private EditPart sourceElement;
+ protected EditPart sourceElement;
/**
*
diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/widgets/StereotypeApplication.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/widgets/StereotypeApplication.java
index 966bbcd8bdb..a582e5baa79 100644
--- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/widgets/StereotypeApplication.java
+++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties/src/org/eclipse/papyrus/uml/properties/widgets/StereotypeApplication.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.properties.widgets;
@@ -59,24 +61,34 @@ public class StereotypeApplication extends AbstractPropertyEditor {
// for editing the data
ModelElement element = input.getModelElement(propertyPath);
if(element instanceof StereotypeApplicationModelElement) {
+ internalDoBinding();
+
+ input.getObservable(propertyPath).addChangeListener(new IChangeListener() {
+ public void handleChange(ChangeEvent event) {
+ // re-do the injection into the stereotype composite because the
+ // underlying model element selection may have been changed
+ internalDoBinding();
+ }
+ });
+ }
+ }
+
+ protected void internalDoBinding() {
+ ModelElement element = input.getModelElement(propertyPath);
+ if(element instanceof StereotypeApplicationModelElement) {
StereotypeApplicationModelElement modelElement = (StereotypeApplicationModelElement)element;
View diagramElement = (View)modelElement.getGraphicalElement();
//EditPart editPart = ((StereotypeApplicationModelElement)element).getEditPart();
final Element umlElement = modelElement.getUMLElement();
- //stereotypeComposite.setSelection(new StructuredSelection(Collections.singletonList(editPart)));
- stereotypeComposite.setElement(umlElement);
- stereotypeComposite.setInput(new StereotypedElementTreeObject(umlElement));
+ if(stereotypeComposite.getElement() != umlElement) {
+ stereotypeComposite.setElement(umlElement);
+ stereotypeComposite.setInput(new StereotypedElementTreeObject(umlElement));
+ }
stereotypeComposite.setDiagramElement(diagramElement);
stereotypeComposite.refresh();
-
- input.getObservable(propertyPath).addChangeListener(new IChangeListener() {
- public void handleChange(ChangeEvent event) {
- stereotypeComposite.refresh();
- }
- });
}
}
}
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/AbstractUMLAggregatedObservableValue.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/AbstractUMLAggregatedObservableValue.java
index 9732eb47bb0..3af456b7a22 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/AbstractUMLAggregatedObservableValue.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/AbstractUMLAggregatedObservableValue.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,15 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.tools.databinding;
import org.eclipse.core.databinding.observable.IObservable;
-import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
+import org.eclipse.papyrus.infra.tools.databinding.ReferenceCountedObservable;
/**
* An Abstract Class for Papyrus Command-based observable values
@@ -22,7 +24,7 @@ import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
* @author Camille Letavernier
*
*/
-public abstract class AbstractUMLAggregatedObservableValue extends AbstractObservableValue implements AggregatedObservable, CommandBasedObservableValue {
+public abstract class AbstractUMLAggregatedObservableValue extends ReferenceCountedObservable.Value implements AggregatedObservable, CommandBasedObservableValue {
protected EditingDomain domain;
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/MultiplicityObservableValue.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/MultiplicityObservableValue.java
index e62380f34b5..3fa6dc61457 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/MultiplicityObservableValue.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/MultiplicityObservableValue.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - 402525
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.tools.databinding;
@@ -17,7 +18,6 @@ import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.IObserving;
-import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.ValueDiff;
import org.eclipse.emf.common.command.Command;
@@ -26,6 +26,7 @@ import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
+import org.eclipse.papyrus.infra.tools.databinding.ReferenceCountedObservable;
import org.eclipse.papyrus.uml.tools.Activator;
import org.eclipse.papyrus.uml.tools.commands.SetMultiplicityCommand;
import org.eclipse.papyrus.uml.tools.helper.UMLDatabindingHelper;
@@ -43,7 +44,7 @@ import org.eclipse.uml2.uml.UMLPackage;
*
* @author Camille Letavernier
*/
-public class MultiplicityObservableValue extends AbstractObservableValue implements IChangeListener, CommandBasedObservableValue, AggregatedObservable, IObserving {
+public class MultiplicityObservableValue extends ReferenceCountedObservable.Value implements IChangeListener, CommandBasedObservableValue, AggregatedObservable, IObserving {
private IObservableValue lowerBound, upperBound, lowerValue, upperValue, lowerValueSpecification, upperValueSpecification;
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/NavigationObservableValue.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/NavigationObservableValue.java
index f2308f0b186..58d689875a9 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/NavigationObservableValue.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/NavigationObservableValue.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - 402525
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.tools.databinding;
@@ -23,7 +24,6 @@ import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.list.IObservableList;
-import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.command.UnexecutableCommand;
@@ -37,6 +37,7 @@ import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
+import org.eclipse.papyrus.infra.tools.databinding.ReferenceCountedObservable;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Property;
@@ -48,7 +49,7 @@ import org.eclipse.uml2.uml.UMLPackage;
*
* @author Camille Letavernier
*/
-public class NavigationObservableValue extends AbstractObservableValue implements IChangeListener, CommandBasedObservableValue, AggregatedObservable, IObserving {
+public class NavigationObservableValue extends ReferenceCountedObservable.Value implements IChangeListener, CommandBasedObservableValue, AggregatedObservable, IObserving {
private Property memberEnd;
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/OwnerObservableValue.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/OwnerObservableValue.java
index 1fab72a0498..0523525d03e 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/OwnerObservableValue.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/OwnerObservableValue.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - 402525
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.tools.databinding;
@@ -22,7 +23,6 @@ import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.list.IObservableList;
-import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.UnexecutableCommand;
import org.eclipse.emf.common.util.EList;
@@ -36,6 +36,7 @@ import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
+import org.eclipse.papyrus.infra.tools.databinding.ReferenceCountedObservable;
import org.eclipse.papyrus.uml.tools.Activator;
import org.eclipse.uml2.uml.Artifact;
import org.eclipse.uml2.uml.Association;
@@ -60,7 +61,7 @@ import org.eclipse.uml2.uml.UMLPackage;
*
* @author Camille Letavernier
*/
-public class OwnerObservableValue extends AbstractObservableValue implements IChangeListener, AggregatedObservable, CommandBasedObservableValue, IObserving {
+public class OwnerObservableValue extends ReferenceCountedObservable.Value implements IChangeListener, AggregatedObservable, CommandBasedObservableValue, IObserving {
private Property memberEnd;
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/PapyrusObservableValue.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/PapyrusObservableValue.java
index 6ae25d3cfbf..99ef34d192d 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/PapyrusObservableValue.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/databinding/PapyrusObservableValue.java
@@ -10,6 +10,7 @@
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation
* Christian W. Damus (CEA) - bug 440108
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.uml.tools.databinding;
@@ -33,6 +34,7 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
+import org.eclipse.papyrus.infra.tools.databinding.ReferenceCountedObservable;
import org.eclipse.papyrus.uml.tools.Activator;
/**
@@ -42,7 +44,9 @@ import org.eclipse.papyrus.uml.tools.Activator;
* @author Camille Letavernier
*
*/
-public class PapyrusObservableValue extends EMFObservableValue implements AggregatedObservable, CommandBasedObservableValue {
+public class PapyrusObservableValue extends EMFObservableValue implements AggregatedObservable, CommandBasedObservableValue, ReferenceCountedObservable {
+
+ private final ReferenceCountedObservable.Support refCount = new ReferenceCountedObservable.Support(this);
/**
*
@@ -119,7 +123,7 @@ public class PapyrusObservableValue extends EMFObservableValue implements Aggreg
return UnexecutableCommand.INSTANCE;
}
-
+
protected IEditCommandRequest createSetRequest(TransactionalEditingDomain domain, EObject owner, EStructuralFeature feature, Object value) {
return new SetRequest(domain, owner, feature, value);
}
@@ -151,4 +155,16 @@ public class PapyrusObservableValue extends EMFObservableValue implements Aggreg
public boolean hasDifferentValues() {
return false; //The value is not aggregated yet
}
+
+ public void retain() {
+ refCount.retain();
+ }
+
+ public void release() {
+ refCount.release();
+ }
+
+ public void autorelease() {
+ refCount.autorelease();
+ }
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractEMFModelElementFactory.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractEMFModelElementFactory.java
new file mode 100644
index 00000000000..4e53be287f0
--- /dev/null
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractEMFModelElementFactory.java
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * 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 417409
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.views.properties.modelelement;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
+
+/**
+ * A partial implementation of a ModelElementFactory for creating {@link EMFModelElement}s
+ *
+ * @author Camille Letavernier
+ *
+ */
+public abstract class AbstractEMFModelElementFactory<T extends EMFModelElement> extends AbstractModelElementFactory<T> {
+
+ @Override
+ protected void updateModelElement(T modelElement, Object newSourceElement) {
+ EObject eObject = EMFHelper.getEObject(newSourceElement);
+ if(eObject == null) {
+ throw new IllegalArgumentException("Cannot resolve EObject selection: " + newSourceElement);
+ }
+
+ updateEMFModelElement(modelElement, eObject);
+ }
+
+ public static void updateEMFModelElement(EMFModelElement modelElement, EObject newEObject) {
+ modelElement.source = newEObject;
+ modelElement.domain = EMFHelper.resolveEditingDomain(newEObject);
+ }
+}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElement.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElement.java
index a69f51490b8..d316c2c8678 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElement.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElement.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,15 +9,24 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import org.eclipse.core.databinding.observable.DisposeEvent;
+import org.eclipse.core.databinding.observable.IDisposeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.infra.tools.databinding.DelegatingObservableValue;
+import org.eclipse.papyrus.infra.tools.databinding.IDelegatingObservable;
+import org.eclipse.papyrus.infra.tools.databinding.ReferenceCountedObservable;
import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory;
import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider;
@@ -29,7 +38,7 @@ import org.eclipse.papyrus.views.properties.creation.PropertyEditorFactory;
*
* @author Camille Letavernier
*/
-public abstract class AbstractModelElement implements ModelElement {
+public abstract class AbstractModelElement implements ModelElement, IDataSourceListener {
/**
* The DataSource owning this ModelElement
@@ -38,11 +47,20 @@ public abstract class AbstractModelElement implements ModelElement {
private final Map<String, IObservable> observables = new HashMap<String, IObservable>();
-
+ private IDisposeListener observableDisposeListener;
+
+ AbstractModelElementFactory<AbstractModelElement> factory;
+
/**
* Constructor.
*/
protected AbstractModelElement() {
+ super();
+ }
+
+ @SuppressWarnings("unchecked")
+ void setFactory(AbstractModelElementFactory<? extends AbstractModelElement> factory) {
+ this.factory = (AbstractModelElementFactory<AbstractModelElement>)factory;
}
public IStaticContentProvider getContentProvider(String propertyPath) {
@@ -74,7 +92,41 @@ public abstract class AbstractModelElement implements ModelElement {
}
public void setDataSource(DataSource source) {
- this.dataSource = source;
+ if(this.dataSource != source) {
+ if(this.dataSource != null) {
+ this.dataSource.removeDataSourceListener(this);
+ }
+
+ this.dataSource = source;
+
+ if(this.dataSource != null) {
+ this.dataSource.addDataSourceListener(this);
+ }
+ }
+ }
+
+ public final void dataSourceChanged(DataSourceChangedEvent event) {
+ if(event.getDataSource() == dataSource) {
+ // The data source changed. Update for the new selection
+ IStructuredSelection selection = dataSource.getSelection();
+ if(selection.isEmpty()) {
+ factory.updateModelElement(this, null);
+ } else if(selection.size() == 1) {
+ factory.updateModelElement(this, selection.getFirstElement());
+ } else {
+ updateMultipleSelection(selection);
+ }
+
+ // Update our observables
+ for(Map.Entry<String, IObservable> next : observables.entrySet()) {
+ IDelegatingObservable wrapper = ((IDelegatingObservable)next.getValue());
+ wrapper.setDelegate(doGetObservable(next.getKey()));
+ }
+ }
+ }
+
+ void updateMultipleSelection(IStructuredSelection selection) {
+ throw new IllegalArgumentException("multiple selection"); //$NON-NLS-1$
}
/**
@@ -100,6 +152,10 @@ public abstract class AbstractModelElement implements ModelElement {
if(!observables.containsKey(propertyPath)) {
IObservable observable = doGetObservable(propertyPath);
if(observable != null) {
+ // Wrap it so that we may replace the delegate as needed
+ observable = DelegatingObservableValue.wrap(observable);
+ observable.addDisposeListener(getObservableDisposeListener());
+ ReferenceCountedObservable.Util.retain(observable);
observables.put(propertyPath, observable);
}
}
@@ -118,15 +174,39 @@ public abstract class AbstractModelElement implements ModelElement {
public void dispose() {
for(IObservable observable : observables.values()) {
- observable.dispose();
+ if(observableDisposeListener != null) {
+ // Don't let the listener concurrently modify the map in case releasing triggers dispose
+ observable.removeDisposeListener(observableDisposeListener);
+ }
+
+ ReferenceCountedObservable.Util.release(observable);
}
+
observables.clear();
+ observableDisposeListener = null;
}
-
- public IValidator getValidator(String propertyPath){
+
+ public IValidator getValidator(String propertyPath) {
return null;
}
-
-
+ private IDisposeListener getObservableDisposeListener() {
+ if(observableDisposeListener == null) {
+ observableDisposeListener = new IDisposeListener() {
+
+ public void handleDispose(DisposeEvent event) {
+ // Remove this property
+ for(Iterator<Map.Entry<String, IObservable>> entries = observables.entrySet().iterator(); entries.hasNext();) {
+ if(entries.next().getValue() == event.getObservable()) {
+ entries.remove();
+ break;
+ }
+ }
+ }
+ };
+ }
+
+ return observableDisposeListener;
+ }
+
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElementFactory.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElementFactory.java
new file mode 100644
index 00000000000..b9517cfee18
--- /dev/null
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AbstractModelElementFactory.java
@@ -0,0 +1,40 @@
+/*
+ * 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.views.properties.modelelement;
+
+import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
+
+
+/**
+ * This is the AbstractModelElementFactory type. Enjoy.
+ */
+public abstract class AbstractModelElementFactory<T extends AbstractModelElement> implements ModelElementFactory {
+
+ protected AbstractModelElementFactory() {
+ super();
+ }
+
+ public final ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ AbstractModelElement result = doCreateFromSource(sourceElement, context);
+
+ if(result != null) {
+ result.setFactory(this);
+ }
+
+ return result;
+ }
+
+ protected abstract T doCreateFromSource(Object sourceElement, DataContextElement context);
+
+ protected abstract void updateModelElement(T modelElement, Object newSourceElement);
+}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AnnotationModelElementFactory.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AnnotationModelElementFactory.java
index 3dd13364b61..8d84047ace7 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AnnotationModelElementFactory.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/AnnotationModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
@@ -23,9 +25,10 @@ import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
*
* @author Camille Letavernier
*/
-public class AnnotationModelElementFactory implements ModelElementFactory {
+public class AnnotationModelElementFactory extends AbstractModelElementFactory<AnnotationModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected AnnotationModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$
@@ -40,4 +43,13 @@ public class AnnotationModelElementFactory implements ModelElementFactory {
return new AnnotationModelElement((EModelElement)source, domain, context.getName());
}
+ @Override
+ protected void updateModelElement(AnnotationModelElement modelElement, Object newSourceElement) {
+ EObject eObject = EMFHelper.getEObject(newSourceElement);
+ if(!(eObject instanceof EModelElement)) {
+ throw new IllegalArgumentException("Cannot resolve EModelElement selection: " + newSourceElement);
+ }
+ modelElement.source = (EModelElement)eObject;
+ modelElement.domain = EMFHelper.resolveEditingDomain(eObject);
+ }
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/CompositeModelElement.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/CompositeModelElement.java
index 0b4573a085f..73e046102df 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/CompositeModelElement.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/CompositeModelElement.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,15 +8,20 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
import org.eclipse.papyrus.infra.tools.databinding.MultipleObservableValue;
import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider;
@@ -34,6 +39,15 @@ import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider;
*/
public class CompositeModelElement extends AbstractModelElement {
+ private final BoundModelElementFactory subModelElementFactory;
+
+
+ public CompositeModelElement(BoundModelElementFactory subModelElementFactory) {
+ super();
+
+ this.subModelElementFactory = subModelElementFactory;
+ }
+
@Override
public IObservable doGetObservable(String propertyPath) {
@@ -69,6 +83,47 @@ public class CompositeModelElement extends AbstractModelElement {
return observableComposite;
}
+ @Override
+ void updateMultipleSelection(IStructuredSelection selection) {
+ ListIterator<ModelElement> subElements = elements.listIterator();
+ Iterator<?> newSourceElements = selection.iterator();
+
+ // Re-use existing sub-elements, just updating them
+ while(newSourceElements.hasNext() && subElements.hasNext()) {
+ ModelElement nextSubElement = subElements.next();
+ if(nextSubElement instanceof AbstractModelElement) {
+ // Can reuse it
+ AbstractModelElement reusable = (AbstractModelElement)nextSubElement;
+ reusable.factory.updateModelElement(reusable, newSourceElements.next());
+ } else {
+ // Replace it
+ nextSubElement.dispose();
+
+ ModelElement newSubElement = subModelElementFactory.createModelElement(newSourceElements.next());
+ if(newSubElement != null) {
+ subElements.set(newSubElement);
+ } else {
+ // TODO: Report a warning?
+ subElements.remove();
+ }
+ }
+ }
+
+ // And create new ones if necessary
+ while(newSourceElements.hasNext()) {
+ ModelElement newSubElement = subModelElementFactory.createModelElement(newSourceElements.next());
+ if(newSubElement != null) {
+ subElements.add(newSubElement);
+ } // TODO: Else report a warning?
+ }
+
+ // And destroy any unneeded sub-elements
+ while(subElements.hasNext()) {
+ subElements.next().dispose();
+ subElements.remove();
+ }
+ }
+
/**
* Adds a sub-model element to this CompositeModelElement
*
@@ -185,4 +240,17 @@ public class CompositeModelElement extends AbstractModelElement {
public List<ModelElement> getSubElements() {
return elements;
}
+
+ //
+ // Nested types
+ //
+
+ /**
+ * Protocol for a factory that a {@link CompositeModelElement} uses to create sub-elements for a multiple
+ * selection. It binds all of the necessary context so that the only input is a selected source element.
+ */
+ public interface BoundModelElementFactory {
+
+ ModelElement createModelElement(Object sourceElement);
+ }
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSource.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSource.java
index 362835a029d..23368e23579 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSource.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSource.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
@@ -9,18 +9,19 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.validation.IValidator;
+import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory;
@@ -50,8 +51,10 @@ import org.eclipse.papyrus.views.properties.contexts.View;
*/
public class DataSource implements IChangeListener {
- private Set<IChangeListener> changeListeners = new HashSet<IChangeListener>();
+ private final ListenerList changeListeners = new ListenerList(ListenerList.IDENTITY);
+ private final ListenerList dataSourceListeners = new ListenerList(ListenerList.IDENTITY);
+
private View view;
private IStructuredSelection selection;
@@ -61,6 +64,7 @@ public class DataSource implements IChangeListener {
/**
* Constructs a new DataSource from the given view and selection
*
+ * @param realm
* @param view
* @param selection
*
@@ -189,13 +193,37 @@ public class DataSource implements IChangeListener {
public void removeChangeListener(IChangeListener listener) {
changeListeners.remove(listener);
}
+
+ public void addDataSourceListener(IDataSourceListener listener) {
+ dataSourceListeners.add(listener);
+ }
+
+ public void removeDataSourceListener(IDataSourceListener listener) {
+ dataSourceListeners.remove(listener);
+ }
public void handleChange(ChangeEvent event) {
- //The set of listeners may change during the update.
- Set<IChangeListener> listeners = new HashSet<IChangeListener>(changeListeners);
-
- for(IChangeListener listener : listeners) {
- listener.handleChange(event);
+ Object[] listeners = changeListeners.getListeners();
+ for(int i = 0; i < listeners.length; i++) {
+ try {
+ ((IChangeListener)listeners[i]).handleChange(event);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in observable change listener.", e); //$NON-NLS-1$
+ }
+ }
+ }
+
+ protected void fireDataSourceChanged() {
+ Object[] listeners = dataSourceListeners.getListeners();
+ if(listeners.length > 0) {
+ DataSourceChangedEvent event = new DataSourceChangedEvent(this);
+ for(int i = 0; i < listeners.length; i++) {
+ try {
+ ((IDataSourceListener)listeners[i]).dataSourceChanged(event);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in data-source listener.", e); //$NON-NLS-1$
+ }
+ }
}
}
@@ -212,6 +240,17 @@ public class DataSource implements IChangeListener {
public IStructuredSelection getSelection() {
return selection;
}
+
+ /**
+ * @param selection the selection to set
+ */
+ public void setSelection(IStructuredSelection selection) {
+ if(!selection.equals(this.selection)) {
+ this.selection = selection;
+
+ fireDataSourceChanged();
+ }
+ }
/**
* @param propertyPath
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceChangedEvent.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceChangedEvent.java
new file mode 100644
index 00000000000..f102926cb9a
--- /dev/null
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceChangedEvent.java
@@ -0,0 +1,32 @@
+/*
+ * 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.views.properties.modelelement;
+
+import java.util.EventObject;
+
+
+/**
+ * This is the DataSourceChangedEvent type. Enjoy.
+ */
+public class DataSourceChangedEvent extends EventObject {
+
+ private static final long serialVersionUID = 1L;
+
+ DataSourceChangedEvent(DataSource source) {
+ super(source);
+ }
+
+ public DataSource getDataSource() {
+ return (DataSource)getSource();
+ }
+}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceFactory.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceFactory.java
index 0a36400fdf8..9dc30680fcd 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceFactory.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSourceFactory.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 435103
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
@@ -107,12 +108,18 @@ public class DataSourceFactory {
* @return The model element corresponding to the given contextElement and
* selection
*/
- private ModelElement createModelElement(DataContextElement contextElement, IStructuredSelection selection) {
+ private ModelElement createModelElement(final DataContextElement contextElement, IStructuredSelection selection) {
if(selection.size() == 1) { // Single Selection
ModelElement modelElement = createFromSource(selection.getFirstElement(), contextElement);
return modelElement;
} else { // MultiSelection
- CompositeModelElement composite = new CompositeModelElement();
+ // Bind the context element in a factory for the composite to create sub-elements
+ CompositeModelElement composite = new CompositeModelElement(new CompositeModelElement.BoundModelElementFactory() {
+
+ public ModelElement createModelElement(Object sourceElement) {
+ return createFromSource(sourceElement, contextElement);
+ }
+ });
Iterator<?> it = selection.iterator();
while(it.hasNext()) {
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/EMFModelElementFactory.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/EMFModelElementFactory.java
index 8877aca5120..6559d7eff55 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/EMFModelElementFactory.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/EMFModelElementFactory.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
@@ -23,9 +25,10 @@ import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
* @author Camille Letavernier
*
*/
-public class EMFModelElementFactory implements ModelElementFactory {
+public class EMFModelElementFactory extends AbstractEMFModelElementFactory<EMFModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected EMFModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
EObject source = EMFHelper.getEObject(sourceElement);
if(source == null) {
Activator.log.warn("Unable to resolve the selected element to an EObject"); //$NON-NLS-1$
@@ -35,5 +38,4 @@ public class EMFModelElementFactory implements ModelElementFactory {
EditingDomain domain = EMFHelper.resolveEditingDomain(source);
return new EMFModelElement(source, domain);
}
-
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/IDataSourceListener.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/IDataSourceListener.java
new file mode 100644
index 00000000000..9e5b9a4b6d2
--- /dev/null
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/IDataSourceListener.java
@@ -0,0 +1,30 @@
+/*
+ * 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.views.properties.modelelement;
+
+import java.util.EventListener;
+
+import org.eclipse.core.databinding.observable.IObservable;
+
+
+/**
+ * A listener protocol for changes to a {@link DataSource} (especially its selection). Data sources are not {@linkplain IObservable observables}
+ * because that would confuse the XWT bindings framework.
+ *
+ * @see DataSource
+ * @see DataSource#addDataSourceListener(IDataSourceListener)
+ */
+public interface IDataSourceListener extends EventListener {
+
+ void dataSourceChanged(DataSourceChangedEvent event);
+}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/PreferencesModelElementFactory.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/PreferencesModelElementFactory.java
index 0aa2db099db..e771d4e3141 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/PreferencesModelElementFactory.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/PreferencesModelElementFactory.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,16 +8,31 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
+import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
-public class PreferencesModelElementFactory implements ModelElementFactory {
+public class PreferencesModelElementFactory extends AbstractModelElementFactory<PreferencesModelElement> {
- public ModelElement createFromSource(Object sourceElement, DataContextElement context) {
+ @Override
+ protected PreferencesModelElement doCreateFromSource(Object sourceElement, DataContextElement context) {
return new PreferencesModelElement(context);
}
+ @Override
+ protected void updateModelElement(PreferencesModelElement modelElement, Object newSourceElement) {
+ if(!(newSourceElement instanceof DataContextElement)) {
+ throw new IllegalArgumentException("Cannot resolve DataContextElement selection: " + newSourceElement);
+ }
+
+ DataContextElement context = (DataContextElement)newSourceElement;
+ modelElement.context = context;
+ modelElement.store = new ScopedPreferenceStore(InstanceScope.INSTANCE, context.getName());
+ }
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/DefaultDisplayEngine.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/DefaultDisplayEngine.java
index dc5360b25b5..a55521e39fb 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/DefaultDisplayEngine.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/DefaultDisplayEngine.java
@@ -15,10 +15,10 @@
package org.eclipse.papyrus.views.properties.runtime;
import java.net.URL;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -40,6 +40,8 @@ import org.eclipse.papyrus.xwt.ILoadingContext;
import org.eclipse.papyrus.xwt.IXWTLoader;
import org.eclipse.papyrus.xwt.XWT;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
@@ -55,12 +57,14 @@ public class DefaultDisplayEngine implements DisplayEngine {
private ILoadingContext loadingContext = new DefaultLoadingContext(getClass().getClassLoader());
- private Set<String> displayedSections = new HashSet<String>();
+ private Map<String, XWTTabDescriptor> currentTabs = new HashMap<String, XWTTabDescriptor>();
- private Set<Control> controls = new HashSet<Control>();
+ private TabModel<DataSource> displayedSections = new TabModel<DataSource>();
+
+ private TabModel<Control> controls = new TabModel<Control>();
private boolean allowDuplicate;
-
+
private Object xmlCache;
/**
@@ -84,7 +88,6 @@ public class DefaultDisplayEngine implements DisplayEngine {
}
public List<ITabDescriptor> getTabDescriptors(Set<View> views) {
-
Map<String, XWTTabDescriptor> result = new LinkedHashMap<String, XWTTabDescriptor>();
Set<String> selectedSections = new HashSet<String>();
@@ -116,20 +119,37 @@ public class DefaultDisplayEngine implements DisplayEngine {
}
}
- disposeControls();
- return new LinkedList<ITabDescriptor>(result.values());
+ for(Map.Entry<String, XWTTabDescriptor> next : result.entrySet()) {
+ XWTTabDescriptor existing = currentTabs.get(next.getKey());
+ if((existing != null) && !existing.equals(next.getValue())) {
+ // Will have to rebuild this tab
+ disposeControls(next.getKey());
+ }
+ }
+
+ currentTabs = result;
+
+ return new ArrayList<ITabDescriptor>(result.values());
}
/**
- * Disposes the controls created by this DisplayEngine
+ * Disposes the controls created by this DisplayEngine for the specified tab ID.
* This should not dispose the engine itself, which can be reused.
*/
- protected void disposeControls() {
- for(Control control : controls) {
+ protected void disposeControls(String tabID) {
+ for(Control control : this.controls.remove(tabID)) {
control.dispose();
}
- displayedSections.clear();
- controls.clear();
+
+ for(DataSource dataSource : displayedSections.remove(tabID)) {
+ dataSource.dispose();
+ }
+ }
+
+ protected void disposeControls() {
+ for(String next : new ArrayList<String>(controls.tabIDs())) {
+ disposeControls(next);
+ }
}
/**
@@ -138,7 +158,7 @@ public class DefaultDisplayEngine implements DisplayEngine {
public void dispose() {
disposeControls();
}
-
+
/**
* Invalidates any caches that I may have because the displayed property UI contexts, constraints, or views have
* changed in some way.
@@ -153,21 +173,54 @@ public class DefaultDisplayEngine implements DisplayEngine {
return null;
}
- if(!allowDuplicate && displayedSections.contains(section.getName())) {
+ DataSource existing = getDataSource(section);
+ if(!allowDuplicate && (existing != null)) {
+ // Update the data source and fire the bindings
+ existing.setSelection(source.getSelection());
+
return null;
}
Control control = createSection(parent, section, loadXWTFile(section), source);
- displayedSections.add(section.getName());
+ addDataSource(section, source);
if(control != null) {
- controls.add(control);
+ addControl(section, control);
}
return control;
}
+ protected DataSource getDataSource(Section section) {
+ return displayedSections.get(section.getTab().getId(), section.getName());
+ }
+
+ /**
+ * Adds a new {@code dataSource} for a property {@code section}.
+ *
+ * @return the previously-recorded data source, if any, for this {@code section} which has now been displaced
+ */
+ protected DataSource addDataSource(Section section, DataSource dataSource) {
+ return displayedSections.put(section.getTab().getId(), section.getName(), dataSource);
+ }
+
+ protected void addControl(Section section, Control control) {
+ final String tabID = section.getTab().getId();
+ final String sectionID = section.getName();
+
+ controls.put(tabID, sectionID, control);
+
+ control.addDisposeListener(new DisposeListener() {
+
+ public void widgetDisposed(DisposeEvent e) {
+ // Perhaps the tabbed properties view is disposing a tab that is not shown by the new selection
+ displayedSections.remove(tabID, sectionID);
+ controls.remove(tabID, sectionID);
+ }
+ });
+ }
+
public void refreshSection(Composite parent, Section section, DataSource source) {
for(Control control : parent.getChildren()) {
control.dispose();
@@ -175,10 +228,10 @@ public class DefaultDisplayEngine implements DisplayEngine {
Control control = createSection(parent, section, loadXWTFile(section), source);
- displayedSections.add(section.getName());
+ addDataSource(section, source);
if(control != null) {
- controls.add(control);
+ addControl(section, control);
}
}
@@ -198,7 +251,7 @@ public class DefaultDisplayEngine implements DisplayEngine {
try {
ResourceSet rset = section.eResource().getResourceSet();
URL url = new URL(null, sectionFile.toString(), new EMFURLStreamHandler(rset.getURIConverter()));
-
+
Map<String, Object> options = new HashMap<String, Object>();
options.put(IXWTLoader.CONTAINER_PROPERTY, parent);
options.put(IXWTLoader.DATACONTEXT_PROPERTY, source);
@@ -208,11 +261,11 @@ public class DefaultDisplayEngine implements DisplayEngine {
if(control != null) {
control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- controls.add(control);
+ addControl(section, control);
}
} catch (Exception ex) {
Activator.log.error("Error while loading " + section.getSectionFile(), ex); //$NON-NLS-1$
- disposeControls();
+ disposeControls(section.getTab().getId());
Label label = new Label(parent, SWT.NONE);
label.setText("An error occured in the property view. The file " + section.getSectionFile() + " could not be loaded"); //$NON-NLS-1$ //$NON-NLS-2$
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/TabModel.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/TabModel.java
new file mode 100644
index 00000000000..da005579afb
--- /dev/null
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/runtime/TabModel.java
@@ -0,0 +1,165 @@
+/*
+ * 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.views.properties.runtime;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * An encapsulation of the hierarchical tab structure of the property sheets managed by a {@link DisplayEngine}.
+ */
+class TabModel<V> {
+
+ private final Map<Path, V> model = new HashMap<Path, V>();
+
+ TabModel() {
+ super();
+ }
+
+ public Set<String> tabIDs() {
+ Set<String> result = new HashSet<String>();
+
+ for(Path next : model.keySet()) {
+ result.add(next.tabID);
+ }
+
+ return Collections.unmodifiableSet(result);
+ }
+
+ public V get(String tabID, String sectionID) {
+ return model.get(new Path(tabID, sectionID));
+ }
+
+ public Collection<V> get(String tabID) {
+ List<V> result = new ArrayList<V>(4);
+
+ Path key = new Path(tabID);
+ for(Map.Entry<Path, V> next : model.entrySet()) {
+ if(next.getKey().equals(key)) {
+ result.add(next.getValue());
+ }
+ }
+
+ return Collections.unmodifiableList(result);
+ }
+
+ public V put(String tabID, String sectionID, V value) {
+ return model.put(new Path(tabID, sectionID), value);
+ }
+
+ public V remove(String tabID, String sectionID) {
+ return model.remove(new Path(tabID, sectionID));
+ }
+
+ public Collection<V> remove(String tabID) {
+ List<V> result = new ArrayList<V>(4);
+
+ Path key = new Path(tabID);
+ for(V next = model.remove(key); next != null; next = model.remove(key)) {
+ result.add(next);
+ }
+
+ return Collections.unmodifiableList(result);
+ }
+
+ public Collection<V> clear() {
+ List<V> result = new ArrayList<V>(model.values());
+
+ model.clear();
+
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("TabModel%s", model.toString()); //$NON-NLS-1$
+ }
+
+ //
+ // Nested types
+ //
+
+ final static class Path {
+
+ // Do not intern this string! Deliberately constructing a new String instance
+ private static final String WILDCARD = new String("*"); //$NON-NLS-1$
+
+ final String tabID;
+
+ final String sectionID;
+
+ Path(String tabID, String sectionID) {
+ checkWildcard(tabID);
+ checkWildcard(sectionID);
+
+ this.tabID = tabID;
+ this.sectionID = sectionID;
+ }
+
+ /**
+ * Create a wildcard path for all sections in a tab.
+ */
+ Path(String tabID) {
+ checkWildcard(tabID);
+
+ this.tabID = tabID;
+ this.sectionID = WILDCARD;
+ }
+
+ static void checkWildcard(String id) {
+ // Deliberately testing for identity of non-interned string
+ if((id == null) || (id == WILDCARD)) {
+ throw new IllegalArgumentException("Attempt to create a wildcard path explicitly"); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("(%s, %s)", tabID, sectionID); //$NON-NLS-1$
+ }
+
+ @Override
+ public int hashCode() {
+ // This isn't great for hash-map performance, but wildcards have to have the same hash as the keys they
+ // match, otherwise using them to access the map won't work
+ return tabID.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(this == obj) {
+ return true;
+ }
+ if(!(obj instanceof Path)) {
+ return false;
+ }
+
+ Path other = (Path)obj;
+ return equals(tabID, other.tabID) && equals(sectionID, other.sectionID);
+ }
+
+ private static boolean equals(String anID, String anotherID) {
+ // Deliberately testing for identity of non-interned string
+ return (anID == WILDCARD) || (anotherID == WILDCARD) || anID.equals(anotherID);
+ }
+
+ }
+
+}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/widgets/AbstractPropertyEditor.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/widgets/AbstractPropertyEditor.java
index 6c452ce7b4f..7e9fe1961cf 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/widgets/AbstractPropertyEditor.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/widgets/AbstractPropertyEditor.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
@@ -9,6 +9,8 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.widgets;
@@ -27,6 +29,8 @@ import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.Context;
import org.eclipse.papyrus.views.properties.contexts.Property;
import org.eclipse.papyrus.views.properties.modelelement.DataSource;
+import org.eclipse.papyrus.views.properties.modelelement.DataSourceChangedEvent;
+import org.eclipse.papyrus.views.properties.modelelement.IDataSourceListener;
import org.eclipse.papyrus.views.properties.runtime.ConfigurationManager;
import org.eclipse.papyrus.views.properties.util.PropertiesUtil;
import org.eclipse.swt.events.DisposeEvent;
@@ -52,6 +56,8 @@ public abstract class AbstractPropertyEditor implements IChangeListener, Customi
* The DataSource representing the semantic objects
*/
protected DataSource input;
+
+ private IDataSourceListener dataSourceListener;
protected boolean readOnly = false;
@@ -83,6 +89,7 @@ public abstract class AbstractPropertyEditor implements IChangeListener, Customi
protected IValidator modelValidator;
protected IConverter targetToModelConverter;
+
/**
* Indicates if the editor's label should be displayed
*/
@@ -299,8 +306,22 @@ public abstract class AbstractPropertyEditor implements IChangeListener, Customi
* @param input
*/
public void setInput(DataSource input) {
- this.input = input;
- checkInput();
+ final DataSource oldInput = this.input;
+ if(input != oldInput) {
+ if(oldInput != null) {
+ oldInput.removeDataSourceListener(getDataSourceListener());
+ }
+
+ this.input = input;
+
+ if(input != null) {
+ input.addDataSourceListener(getDataSourceListener());
+ }
+
+ // Only do this after attaching our listener so that it will be ahead of
+ // any ModelElements created for properties
+ checkInput();
+ }
}
/**
@@ -565,4 +586,36 @@ public abstract class AbstractPropertyEditor implements IChangeListener, Customi
return modelValidator;
}
+ private IDataSourceListener getDataSourceListener() {
+ if(dataSourceListener == null) {
+ dataSourceListener = new IDataSourceListener() {
+
+ public void dataSourceChanged(DataSourceChangedEvent event) {
+ // The data source's selection changed. Update my validator or clear it if now there is none
+ IObservableValue observable = AbstractPropertyEditor.this.observableValue;
+
+ if((observable != null) && (modelValidator != null) && (valueEditor != null) && !valueEditor.isDisposed()) {
+ modelValidator = null;
+
+ // First, clear the validator to disable validation
+ valueEditor.setStrategies();
+ valueEditor.setModelValidator(null);
+
+ // Then re-enable to later when ready for user input
+ observable.getRealm().asyncExec(new Runnable() {
+
+ public void run() {
+ if((valueEditor != null) && !valueEditor.isDisposed()) {
+ valueEditor.setStrategies();
+ valueEditor.setModelValidator(getValidator());
+ }
+ }
+ });
+ }
+ }
+ };
+ }
+
+ return dataSourceListener;
+ }
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSection.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSection.java
index 074caeaf9e0..c282fcc67aa 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSection.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSection.java
@@ -9,6 +9,7 @@
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 435420
+ * Christian W. Damus (CEA) - bug 417409
*
*****************************************************************************/
package org.eclipse.papyrus.views.properties.xwt;
@@ -116,15 +117,18 @@ public class XWTSection extends AbstractPropertySection implements IChangeListen
}
private void setSource(DataSource source) {
- if(this.source != null) {
- this.source.removeChangeListener(this);
- this.source.dispose();
- }
+ final DataSource oldSource = this.source;
+
+ if(oldSource != source) {
+ if(oldSource != null) {
+ oldSource.removeChangeListener(this);
+ }
- this.source = source;
+ this.source = source;
- if(section.getConstraints().size() > 0) {
- source.addChangeListener(this);
+ if(section.getConstraints().size() > 0) {
+ source.addChangeListener(this);
+ }
}
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSectionDescriptor.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSectionDescriptor.java
index 17161e129b9..1907ddffdb4 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSectionDescriptor.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTSectionDescriptor.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 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.xwt;
@@ -73,5 +75,35 @@ public class XWTSectionDescriptor extends AbstractSectionDescriptor {
return true;
}
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + System.identityHashCode(display);
+ result = prime * result + System.identityHashCode(section);
+ result = prime * result + System.identityHashCode(view);
+ return result;
+ }
+
+ /**
+ * XWT section descriptors are equal if they have the same (identical) references to the section and view from the property-sheet model
+ * and are associated with the same display engine.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ boolean result;
+
+ if(this == obj) {
+ result = true;
+ } else if((obj == null) || (obj.getClass() != this.getClass())) {
+ result = false;
+ } else {
+ XWTSectionDescriptor other = (XWTSectionDescriptor)obj;
+
+ result = (other.section == this.section) && (other.view == this.view) && (other.display == this.display);
+ }
+
+ return result;
+ }
}
diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTTabDescriptor.java b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTTabDescriptor.java
index d4a4b84f240..0c7ed473d80 100644
--- a/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTTabDescriptor.java
+++ b/plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/xwt/XWTTabDescriptor.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,9 +8,13 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 417409
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.properties.xwt;
+import java.util.List;
+
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.Section;
import org.eclipse.papyrus.views.properties.contexts.Tab;
@@ -104,4 +108,37 @@ public class XWTTabDescriptor extends AbstractTabDescriptor {
public int getPriority() {
return tab.getPriority();
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ List<?> sectionDescriptors = getSectionDescriptors();
+ result = prime * result + ((tab == null) ? 0 : tab.hashCode());
+ result = prime * result + ((sectionDescriptors == null) ? 0 : sectionDescriptors.hashCode());
+ return result;
+ }
+
+ /**
+ * XWT tab descriptors are equal if they have the same ID and an equal list (in order) of section descriptors.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ boolean result;
+
+ if(this == obj) {
+ result = true;
+ } else if((obj == null) || (obj.getClass() != this.getClass())) {
+ result = false;
+ } else {
+ XWTTabDescriptor other = (XWTTabDescriptor)obj;
+
+ result = (other.getId() == null) ? this.getId() == null : (other.getId().equals(this.getId()));
+ if(result) {
+ result = (other.getSectionDescriptors() == null) ? this.getSectionDescriptors() == null : other.getSectionDescriptors().equals(this.getSectionDescriptors());
+ }
+ }
+
+ return result;
+ }
}

Back to the top