Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2016-02-26 22:53:17 +0000
committerGerrit Code Review @ Eclipse.org2016-03-02 12:24:34 +0000
commite9bbbbcbef810b952d2c98caaa18d711eabd3a7f (patch)
tree01b7698fa73401e9b7e173cfb59b6d67d6f41202 /plugins/infra/emf
parent387194dfad69c05dae22afe2548109b267091ea1 (diff)
downloadorg.eclipse.papyrus-e9bbbbcbef810b952d2c98caaa18d711eabd3a7f.tar.gz
org.eclipse.papyrus-e9bbbbcbef810b952d2c98caaa18d711eabd3a7f.tar.xz
org.eclipse.papyrus-e9bbbbcbef810b952d2c98caaa18d711eabd3a7f.zip
Bug 474467: Papyrus editors title do not update when their label change
Add support for propagation of label-provider change events for labels that are dependent on other elements' labels. Implement such a dependent label for all notation views supported by the Viewpoints mechanism that have no names of their own, including * unnamed Diagrams * unnamed Tables Now that the table label provider depends on table prototypes, the broken prototype references in editor reload tests need to be updated (they were missed in the refactoring when all of the prototypes were removed from the builtin Viewpoints configuration model). Change-Id: I8a9c361129c996188f87ac2851db39e0f66f3acd
Diffstat (limited to 'plugins/infra/emf')
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/DependentEMFLabelProvider.java161
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java648
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/ForwardingEMFLabelProvider.java82
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java16
4 files changed, 599 insertions, 308 deletions
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/DependentEMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/DependentEMFLabelProvider.java
new file mode 100644
index 00000000000..172c59496c0
--- /dev/null
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/DependentEMFLabelProvider.java
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus 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 - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.ui.emf.providers;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+
+import com.google.common.collect.MapMaker;
+import com.google.common.collect.Sets;
+
+/**
+ * A specialized {@link EMFLabelProvider} for label providers that compute labels
+ * for objects from labels of objects on which they depend. For example, in a
+ * banking system, an account label may be something like "Fred's Chequing"
+ * in which the label depends on the label of the account holder. If the holder's
+ * name changes from "Fred" to something else, the account's label also must be
+ * recomputed.
+ */
+public class DependentEMFLabelProvider extends EMFLabelProvider {
+
+ private SubscriptionListener subscriptionListener;
+
+ private final CopyOnWriteArrayList<ILabelProviderListener> listeners = new CopyOnWriteArrayList<>();
+
+ public DependentEMFLabelProvider() {
+ super(new ForwardingEMFLabelProvider());
+ }
+
+ @Override
+ public void dispose() {
+ if (subscriptionListener != null) {
+ subscriptionListener.dispose();
+ }
+
+ super.dispose();
+ }
+
+ /**
+ * Subscribe to label changes of the given {@code object} to notify that its
+ * {@code dependent}'s label accordingly changes.
+ *
+ * @param object
+ * an object to listen to
+ * @param dependent
+ * an object that depends on its labels
+ */
+ protected void subscribe(EObject object, EObject dependent) {
+ if (baseEMFLabelProvider instanceof ForwardingEMFLabelProvider) {
+ SubscriptionListener subs = getSubscriptionListener();
+ subs.add(object, dependent);
+ }
+ }
+
+ /**
+ * Unsubscribe from label changes of the given {@code object} because the
+ * {@link dependent}'s labels no longer depend on it.
+ *
+ * @param object
+ * an object to listen to
+ * @param dependent
+ * an object that no longer depends on its labels
+ */
+ protected void unsubscribe(EObject object, EObject dependent) {
+ // If we didn't create the listener, yet, then it can't be attached to anything
+ if (subscriptionListener != null) {
+ subscriptionListener.remove(object, dependent);
+ }
+ }
+
+ private SubscriptionListener getSubscriptionListener() {
+ if (subscriptionListener == null) {
+ subscriptionListener = new SubscriptionListener();
+ ((ForwardingEMFLabelProvider) baseEMFLabelProvider).addListener(subscriptionListener);
+ }
+
+ return subscriptionListener;
+ }
+
+ @Override
+ public void addListener(ILabelProviderListener listener) {
+ super.addListener(listener);
+ listeners.addIfAbsent(listener);
+ }
+
+ @Override
+ public void removeListener(ILabelProviderListener listener) {
+ listeners.remove(listener);
+ super.removeListener(listener);
+ }
+
+ protected void fireLabelProviderChange(Object object) {
+ if (!listeners.isEmpty()) {
+ LabelProviderChangedEvent event = new LabelProviderChangedEvent(this, object);
+ listeners.forEach(l -> l.labelProviderChanged(event));
+ }
+ }
+
+ //
+ // Nested types
+ //
+
+ private class SubscriptionListener implements ILabelProviderListener {
+ private final Map<EObject, Set<EObject>> subscriptions = new MapMaker().weakKeys().makeMap();
+
+ @Override
+ public void labelProviderChanged(LabelProviderChangedEvent event) {
+ Set<EObject> dependents = subscriptions.get(event.getElement());
+ if (dependents != null) {
+ dependents.forEach(DependentEMFLabelProvider.this::fireLabelProviderChange);
+ }
+ }
+
+ void add(EObject subscription, EObject dependent) {
+ subscriptions.computeIfAbsent(subscription, x -> Sets.newSetFromMap(new WeakHashMap<>()))
+ .add(dependent);
+ }
+
+ void remove(EObject subscription, EObject dependent) {
+ Set<EObject> dependents = subscriptions.get(subscription);
+ if (dependents != null) {
+ dependents.remove(dependent);
+ if (dependents.isEmpty()) {
+ subscriptions.remove(subscription);
+ }
+ if (subscriptions.isEmpty()) {
+ this.dispose();
+ }
+ }
+ }
+
+ void dispose() {
+ if (baseEMFLabelProvider instanceof ForwardingEMFLabelProvider) {
+ ((ForwardingEMFLabelProvider) baseEMFLabelProvider).removeListener(this);
+ }
+
+ subscriptions.clear();
+
+ if (subscriptionListener == this) {
+ subscriptionListener = null;
+ }
+ }
+ }
+
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java
index 20e055e6a78..0a970d1c29c 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java
@@ -1,302 +1,346 @@
-/*****************************************************************************
- * Copyright (c) 2011 CEA LIST.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.ui.emf.providers;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.TreeElement;
-import org.eclipse.papyrus.emf.facet.custom.ui.internal.DecoratingCustomizedLabelProvider;
-import org.eclipse.papyrus.emf.facet.custom.ui.internal.ResolvingCustomizedLabelProvider;
-import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
-import org.eclipse.papyrus.infra.services.labelprovider.service.IDetailLabelProvider;
-import org.eclipse.papyrus.infra.services.labelprovider.service.IQualifierLabelProvider;
-import org.eclipse.papyrus.infra.ui.internal.emf.Activator;
-import org.eclipse.swt.graphics.Image;
-
-/**
- * This class handles labels for EMF Objects
- * The class can handle the following cases :
- * - An EObject (Which can be resolved with {@link EMFHelper#getEObject(Object)})
- * - A IStructuredSelection containing EObject(s)
- *
- * @author Camille Letavernier
- */
-public class EMFLabelProvider extends ResolvingCustomizedLabelProvider implements IDetailLabelProvider, IQualifierLabelProvider {
-
- protected ILabelProvider baseEMFLabelProvider;
-
- /**
- * Creates a new EMFObjectLabelProvider.
- */
- public EMFLabelProvider() {
- super(new DecoratingCustomizedLabelProvider(Activator.getDefault().getCustomizationManager())); // Note: CustomizableModelLabelProvider doesn't use the CustomizationManager. It relies on the content provider's CustomizationManager
- baseEMFLabelProvider = new StandardEMFLabelProvider();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getText(Object element) {
- if (element == null) {
- return ""; //$NON-NLS-1$
- }
-
- if (element instanceof TreeElement) {
- return super.getText(element);
- }
-
- EObject eObject = EMFHelper.getEObject(element);
- if (eObject != null) {
- return getText(eObject);
- }
-
- if (element instanceof IStructuredSelection) {
- return getText((IStructuredSelection) element);
- }
-
- return element.toString();
- }
-
- protected String getText(EObject element) {
- return baseEMFLabelProvider.getText(element);
- }
-
- protected String getText(IStructuredSelection selection) {
- if (selection.isEmpty()) {
- return ""; //$NON-NLS-1$
- }
-
- if (selection.size() == 1) {
- return getText(selection.getFirstElement());
- } else {
- final List<?> selectionAsList = selection.toList();
- String str = "";
- for (int i = 0; i < selectionAsList.size(); i++) {
- final String txt = getText(selectionAsList.get(i));
- if (txt != null) {
- str += txt;
- }
- if (i < selectionAsList.size() - 1) {
- str += ", ";
- }
- }
- return str;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Image getImage(Object element) {
- if (element instanceof TreeElement) {
- return super.getImage(element);
- }
-
- EObject eObject = EMFHelper.getEObject(element);
- if (eObject != null) {
- return getImage(eObject);
- }
-
- if (element instanceof IStructuredSelection) {
- return getImage((IStructuredSelection) element);
- }
-
- return null;
- }
-
- protected Image getImage(EObject eObject) {
- return baseEMFLabelProvider.getImage(eObject);
- }
-
- protected Image getImage(IStructuredSelection selection) {
- if (selection.isEmpty()) {
- return null;
- } else if (selection.size() == 1) {
- return getImage(selection.getFirstElement());
- }
-
- final List<?> selectionAsList = selection.toList();
- final Set<EObject> selectedEObject = new HashSet<EObject>();
- boolean isEObjectSelection = true;
- for (final Object current : selectionAsList) {
- final EObject obj = EMFHelper.getEObject(current);
- if (obj != null) {
- selectedEObject.add(obj);
- } else {
- isEObjectSelection = false;
- }
- }
-
- if (isEObjectSelection) {// all selected elements are EObject
- if (selectedEObject.size() == 1 || hasCommonImage(selectedEObject)) {
- return getImage(selectedEObject.toArray()[0]);
- } else {
- final EClass common = org.eclipse.papyrus.emf.facet.util.emf.core.internal.EMFUtils.computeLeastCommonSupertype(getEClasses(selectedEObject));
- if (!common.isAbstract()) {
- // FIXME : the label provider service should manage this case
- final Object instance = common.getEPackage().getEFactoryInstance().create(common);
- return getNonCommonIcon(instance);
- }
- }
- } else if (selectedEObject.size() == 0) {
- // the multiple selection contains any EObject
- } else {
- // the selection contains EObject and others elements
- }
- return null;
- }
-
- /**
- *
- * @param objects
- * a collection of objects
- * @return
- * <code>true</code> if the image found for each object is the same <code>false</code> of if the collection is empty or the image returned
- * for each object is not the same
- */
- protected boolean hasCommonImage(final Collection<?> objects) {
- if (!objects.isEmpty()) {
- final Image lastImage = getImage(objects.toArray()[0]);
- for (final Object current : objects) {
- if (lastImage != getImage(current)) {
- return false;
- }
- }
- } else {
- return false;
- }
- return true;
- }
-
- /**
- *
- * @param commonEClass
- * the eClass
- * @return
- * the icon to use for this eclass
- */
- protected Image getNonCommonIcon(final Object commonObject) {
- return getImage(commonObject);
- }
-
- /**
- *
- * @param objects
- * a collection of eobject
- * @return
- * the set of eclasses for the parameter objects
- */
- private Set<EClass> getEClasses(final Collection<EObject> objects) {
- final Set<EClass> eclasses = new HashSet<EClass>();
- for (final EObject current : objects) {
- eclasses.add(current.eClass());
- }
- return eclasses;
- }
-
- public String getDetail(Object object) {
- object = EMFHelper.getEObject(object);
- return getText(object) + " - " + getQualifiedClassName(object); //$NON-NLS-1$
- }
-
- /**
- * Returns the qualified Class name of the given EObject, or an
- * empty String if the object is not an EObject
- *
- * @param object
- * @return The qualified name of this object's class, or an empty
- * String if the object is not an EObject
- */
- protected String getQualifiedClassName(Object object) {
- if (object instanceof EObject) {
- EObject eObject = (EObject) object;
- EClass eClass = eObject.eClass();
- return EMFHelper.getQualifiedName(eClass, "::"); //$NON-NLS-1$
- }
- return ""; //$NON-NLS-1$
- }
-
-
-
- public String getQualifierText(Object element) {
- String result = null;
-
- EObject parent = getParentObject(element);
- if (parent != null) {
- result = getQualifiedText(parent);
- }
-
- return result;
- }
-
- private EObject getParentObject(Object element) {
- EObject result = null;
-
- if (element != null) {
- EObject eObject = EMFHelper.getEObject(element);
- if (eObject != null) {
- result = getParent(eObject);
- }
- }
-
- return result;
- }
-
- public Image getQualifierImage(Object element) {
- Image result = null;
-
- EObject parent = getParentObject(element);
- if (parent != null) {
- result = getImage(parent);
- }
-
- return result;
- }
-
- protected EObject getParent(EObject object) {
- return object.eContainer();
- }
-
- protected String getQualifiedText(EObject object) {
- StringBuilder result = new StringBuilder();
-
- appendQualifiedText(object, result);
-
- return result.toString();
- }
-
- protected void appendQualifiedText(EObject object, StringBuilder buf) {
- EObject parent = getParent(object);
- if (parent != null) {
- appendQualifiedText(parent, buf);
- }
-
- if (buf.length() > 0) {
- buf.append("::");
- }
-
- String name = getText(object);
- if (name == null) {
- name = String.format("<%s>", object.eClass().getName());
- }
- buf.append(name);
- }
-}
+/*****************************************************************************
+ * Copyright (c) 2011, 2016 CEA LIST, Christian W. Damus, 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 - bug 474467
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.ui.emf.providers;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.TreeElement;
+import org.eclipse.papyrus.emf.facet.custom.ui.internal.DecoratingCustomizedLabelProvider;
+import org.eclipse.papyrus.emf.facet.custom.ui.internal.ResolvingCustomizedLabelProvider;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
+import org.eclipse.papyrus.infra.services.labelprovider.service.IDetailLabelProvider;
+import org.eclipse.papyrus.infra.services.labelprovider.service.IQualifierLabelProvider;
+import org.eclipse.papyrus.infra.ui.internal.emf.Activator;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * This class handles labels for EMF Objects
+ * The class can handle the following cases :
+ * - An EObject (Which can be resolved with {@link EMFHelper#getEObject(Object)})
+ * - A IStructuredSelection containing EObject(s)
+ *
+ * @author Camille Letavernier
+ */
+public class EMFLabelProvider extends ResolvingCustomizedLabelProvider implements IDetailLabelProvider, IQualifierLabelProvider {
+
+ protected ILabelProvider baseEMFLabelProvider;
+
+ /**
+ * Creates a new EMFObjectLabelProvider.
+ */
+ public EMFLabelProvider() {
+ this(new StandardEMFLabelProvider());
+ }
+
+ EMFLabelProvider(ILabelProvider baseEMFLabelProvider) {
+ // Note: CustomizableModelLabelProvider doesn't use the CustomizationManager.
+ // It relies on the content provider's CustomizationManager
+ super(new DecoratingCustomizedLabelProvider(Activator.getDefault().getCustomizationManager()));
+ this.baseEMFLabelProvider = baseEMFLabelProvider;
+ }
+
+ @Override
+ public void dispose() {
+ baseEMFLabelProvider.dispose();
+
+ super.dispose();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getText(Object element) {
+ if (element == null) {
+ return ""; //$NON-NLS-1$
+ }
+
+ if (element instanceof TreeElement) {
+ return super.getText(element);
+ }
+
+ EObject eObject = EMFHelper.getEObject(element);
+ if (eObject != null) {
+ return getText(eObject);
+ }
+
+ if (element instanceof IStructuredSelection) {
+ return getText((IStructuredSelection) element);
+ }
+
+ return element.toString();
+ }
+
+ protected String getText(EObject element) {
+ return baseEMFLabelProvider.getText(element);
+ }
+
+ protected String getText(IStructuredSelection selection) {
+ if (selection.isEmpty()) {
+ return ""; //$NON-NLS-1$
+ }
+
+ if (selection.size() == 1) {
+ return getText(selection.getFirstElement());
+ } else {
+ final List<?> selectionAsList = selection.toList();
+ String str = "";
+ for (int i = 0; i < selectionAsList.size(); i++) {
+ final String txt = getText(selectionAsList.get(i));
+ if (txt != null) {
+ str += txt;
+ }
+ if (i < selectionAsList.size() - 1) {
+ str += ", ";
+ }
+ }
+ return str;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Image getImage(Object element) {
+ if (element instanceof TreeElement) {
+ return super.getImage(element);
+ }
+
+ EObject eObject = EMFHelper.getEObject(element);
+ if (eObject != null) {
+ return getImage(eObject);
+ }
+
+ if (element instanceof IStructuredSelection) {
+ return getImage((IStructuredSelection) element);
+ }
+
+ return null;
+ }
+
+ protected Image getImage(EObject eObject) {
+ return baseEMFLabelProvider.getImage(eObject);
+ }
+
+ protected Image getImage(IStructuredSelection selection) {
+ if (selection.isEmpty()) {
+ return null;
+ } else if (selection.size() == 1) {
+ return getImage(selection.getFirstElement());
+ }
+
+ final List<?> selectionAsList = selection.toList();
+ final Set<EObject> selectedEObject = new HashSet<EObject>();
+ boolean isEObjectSelection = true;
+ for (final Object current : selectionAsList) {
+ final EObject obj = EMFHelper.getEObject(current);
+ if (obj != null) {
+ selectedEObject.add(obj);
+ } else {
+ isEObjectSelection = false;
+ }
+ }
+
+ if (isEObjectSelection) {// all selected elements are EObject
+ if (selectedEObject.size() == 1 || hasCommonImage(selectedEObject)) {
+ return getImage(selectedEObject.toArray()[0]);
+ } else {
+ final EClass common = org.eclipse.papyrus.emf.facet.util.emf.core.internal.EMFUtils.computeLeastCommonSupertype(getEClasses(selectedEObject));
+ if (!common.isAbstract()) {
+ // FIXME : the label provider service should manage this case
+ final Object instance = common.getEPackage().getEFactoryInstance().create(common);
+ return getNonCommonIcon(instance);
+ }
+ }
+ } else if (selectedEObject.size() == 0) {
+ // the multiple selection contains any EObject
+ } else {
+ // the selection contains EObject and others elements
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @param objects
+ * a collection of objects
+ * @return
+ * <code>true</code> if the image found for each object is the same <code>false</code> of if the collection is empty or the image returned
+ * for each object is not the same
+ */
+ protected boolean hasCommonImage(final Collection<?> objects) {
+ if (!objects.isEmpty()) {
+ final Image lastImage = getImage(objects.toArray()[0]);
+ for (final Object current : objects) {
+ if (lastImage != getImage(current)) {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ *
+ * @param commonEClass
+ * the eClass
+ * @return
+ * the icon to use for this eclass
+ */
+ protected Image getNonCommonIcon(final Object commonObject) {
+ return getImage(commonObject);
+ }
+
+ /**
+ *
+ * @param objects
+ * a collection of eobject
+ * @return
+ * the set of eclasses for the parameter objects
+ */
+ private Set<EClass> getEClasses(final Collection<EObject> objects) {
+ final Set<EClass> eclasses = new HashSet<EClass>();
+ for (final EObject current : objects) {
+ eclasses.add(current.eClass());
+ }
+ return eclasses;
+ }
+
+ @Override
+ public String getDetail(Object object) {
+ object = EMFHelper.getEObject(object);
+ return getText(object) + " - " + getQualifiedClassName(object); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the qualified Class name of the given EObject, or an
+ * empty String if the object is not an EObject
+ *
+ * @param object
+ * @return The qualified name of this object's class, or an empty
+ * String if the object is not an EObject
+ */
+ protected String getQualifiedClassName(Object object) {
+ if (object instanceof EObject) {
+ EObject eObject = (EObject) object;
+ EClass eClass = eObject.eClass();
+ return EMFHelper.getQualifiedName(eClass, "::"); //$NON-NLS-1$
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+
+
+ @Override
+ public String getQualifierText(Object element) {
+ String result = null;
+
+ EObject parent = getParentObject(element);
+ if (parent != null) {
+ result = getQualifiedText(parent);
+ }
+
+ return result;
+ }
+
+ private EObject getParentObject(Object element) {
+ EObject result = null;
+
+ if (element != null) {
+ EObject eObject = EMFHelper.getEObject(element);
+ if (eObject != null) {
+ result = getParent(eObject);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public Image getQualifierImage(Object element) {
+ Image result = null;
+
+ EObject parent = getParentObject(element);
+ if (parent != null) {
+ result = getImage(parent);
+ }
+
+ return result;
+ }
+
+ protected EObject getParent(EObject object) {
+ return object.eContainer();
+ }
+
+ protected String getQualifiedText(EObject object) {
+ StringBuilder result = new StringBuilder();
+
+ appendQualifiedText(object, result);
+
+ return result.toString();
+ }
+
+ protected void appendQualifiedText(EObject object, StringBuilder buf) {
+ EObject parent = getParent(object);
+ if (parent != null) {
+ appendQualifiedText(parent, buf);
+ }
+
+ if (buf.length() > 0) {
+ buf.append("::");
+ }
+
+ String name = getText(object);
+ if (name == null) {
+ name = String.format("<%s>", object.eClass().getName());
+ }
+ buf.append(name);
+ }
+
+ @Override
+ public void addListener(ILabelProviderListener listener) {
+ super.addListener(listener);
+ baseEMFLabelProvider.addListener(listener);
+
+ // If we're adding a listener to it, presumably we want its
+ // notifications, so enable them
+ if (baseEMFLabelProvider.getClass() == StandardEMFLabelProvider.class) {
+ // Replace it with a fowarding provider
+ baseEMFLabelProvider.dispose();
+ baseEMFLabelProvider = new ForwardingEMFLabelProvider();
+ baseEMFLabelProvider.addListener(listener);
+ } else if (baseEMFLabelProvider instanceof AdapterFactoryLabelProvider) {
+ // Trust that it will notify if enabled
+ ((AdapterFactoryLabelProvider) baseEMFLabelProvider).setFireLabelUpdateNotifications(true);
+ }
+ }
+
+ @Override
+ public void removeListener(ILabelProviderListener listener) {
+ baseEMFLabelProvider.removeListener(listener);
+ super.removeListener(listener);
+ }
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/ForwardingEMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/ForwardingEMFLabelProvider.java
new file mode 100644
index 00000000000..a998f1a1097
--- /dev/null
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/ForwardingEMFLabelProvider.java
@@ -0,0 +1,82 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus 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 - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.ui.emf.providers;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.edit.provider.IChangeNotifier;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.edit.provider.INotifyChangedListener;
+
+import com.google.common.collect.MapMaker;
+
+/**
+ * A specialized {@link StandardEMFLabelProvider} that forwards change notifications
+ * from the label-providers to which it delegates. By default, it
+ * {@linkplain #isFireLabelUpdateNotifications() fires label update notifications}
+ * because that is the presumed purpose of using this class in the first place.
+ */
+public class ForwardingEMFLabelProvider extends StandardEMFLabelProvider {
+
+ // Need to track this because EMF's change notifiers don't prevent multiple attachment
+ // of the same listener
+ private final ConcurrentMap<IChangeNotifier, INotifyChangedListener> forwards = new MapMaker().weakKeys().weakValues().makeMap();
+
+ private INotifyChangedListener forwardingListener;
+
+ public ForwardingEMFLabelProvider() {
+ super();
+
+ // I am used in contexts where JFace label provider events are needed
+ setFireLabelUpdateNotifications(true);
+ }
+
+ @Override
+ public void dispose() {
+ try {
+ for (Map.Entry<IChangeNotifier, INotifyChangedListener> next : forwards.entrySet()) {
+ next.getKey().removeListener(next.getValue());
+ }
+ forwards.clear();
+ } finally {
+ super.dispose();
+ }
+ }
+
+ @Override
+ IItemLabelProvider adapt(AdapterFactory adapterFactory, EObject object) {
+ IItemLabelProvider result = super.adapt(adapterFactory, object);
+
+ if (result instanceof IChangeNotifier) {
+ // Hook it up for forwarding
+ IChangeNotifier notifier = (IChangeNotifier) result;
+ if (forwards.putIfAbsent(notifier, getForwardingListener()) == null) {
+ notifier.addListener(getForwardingListener());
+ }
+ }
+
+ return result;
+ }
+
+ private INotifyChangedListener getForwardingListener() {
+ if (forwardingListener == null) {
+ forwardingListener = notification -> notifyChanged(notification);
+ }
+ return forwardingListener;
+ }
+
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java
index d659ec48007..62b12fa7200 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java
@@ -1,5 +1,6 @@
/*******************************************************************************
- * Copyright (c) 2008 Obeo.
+ * Copyright (c) 2008, 2016 Obeo, CEA LIST, Christian W. Damus, 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 +10,8 @@
* Obeo - initial API and implementation
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Added support for enum literals
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Implementation of IDetailLabelProvider
+ * Christian W. Damus - bug 474467
+ *
*******************************************************************************/
package org.eclipse.papyrus.infra.ui.emf.providers;
@@ -42,9 +45,6 @@ import org.eclipse.swt.graphics.Image;
*/
public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implements IDetailLabelProvider {
- /** item provider class */
- private static final Class<?> IItemLabelProviderClass = IItemLabelProvider.class;
-
/** list of adapter factories, identified by their Ids */
private static Map<String, AdapterFactory> factories = new HashMap<String, AdapterFactory>();
@@ -154,12 +154,16 @@ public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implem
if (eObject != null) {
AdapterFactory adapterFactory = getEditFactory(eObject);
if (adapterFactory != null) {
- return (IItemLabelProvider) adapterFactory.adapt(eObject, IItemLabelProviderClass);
+ itemLabelProvider = adapt(adapterFactory, eObject);
}
}
return itemLabelProvider;
}
+ IItemLabelProvider adapt(AdapterFactory adapterFactory, EObject object) {
+ return (IItemLabelProvider) adapterFactory.adapt(object, IItemLabelProvider.class);
+ }
+
/**
* Gets the edit factory.
*
@@ -205,6 +209,7 @@ public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implem
return factory;
}
+ @Override
public String getDetail(Object object) {
object = EMFHelper.getEObject(object);
return getText(object) + " - " + getQualifiedClassName(object); //$NON-NLS-1$
@@ -226,5 +231,4 @@ public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implem
}
return ""; //$NON-NLS-1$
}
-
}

Back to the top