Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2014-12-19 22:45:17 +0000
committerChristian W. Damus2015-01-05 15:45:16 +0000
commitde642b8cdba0a0bb5843e19b086863419d55456a (patch)
treef3aa5e77023e3aea7486781e6b8210d08b0321cc /plugins
parentfdb0c07062f3b4162ec63ff9061c4584bb7ee2f4 (diff)
downloadorg.eclipse.papyrus-de642b8cdba0a0bb5843e19b086863419d55456a.tar.gz
org.eclipse.papyrus-de642b8cdba0a0bb5843e19b086863419d55456a.tar.xz
org.eclipse.papyrus-de642b8cdba0a0bb5843e19b086863419d55456a.zip
455075: [Properties View] Providers instantiated from DataSource are never updated.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=455075 Implement a delegation strategy for content providers and label providers created by the DataSource. When its selection is changed, the providers created by a data source ditch and re-create their delegates.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java21
-rw-r--r--plugins/views/properties/org.eclipse.papyrus.views.properties/src/org/eclipse/papyrus/views/properties/modelelement/DataSource.java132
2 files changed, 149 insertions, 4 deletions
diff --git a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java
index 9dcfd50fd82..2358f17c527 100644
--- a/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java
+++ b/plugins/infra/widget/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 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
@@ -8,6 +8,8 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus - bug 455075
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.providers;
@@ -102,6 +104,23 @@ public class EncapsulatedContentProvider implements IHierarchicContentProvider,
// encapsulated = null;
}
+ /**
+ * Updates me to encapsulate a new {@code delegate}. If it makes sense for a particular instance, this may
+ * collapse any chain of providers that are exactly of {@link EncapsulatedContentProvider} type (not some
+ * subclass that may have different behaviour). If it is necessary to delegate to another encapsulated
+ * instance as is, then simply assign the protected {@link #encapsulated} field.
+ *
+ * @param delegate
+ * my new delegate, or {@code null} to simply forget the previous delegate
+ */
+ protected void encapsulate(IStructuredContentProvider delegate) {
+ while ((delegate != null) && (delegate.getClass() == EncapsulatedContentProvider.class)) {
+ delegate = ((EncapsulatedContentProvider) delegate).encapsulated;
+ }
+
+ this.encapsulated = delegate;
+ }
+
protected void addViewerFilter(StructuredViewer viewer, ViewerFilter filter) {
Set<ViewerFilter> currentFilters = new LinkedHashSet<ViewerFilter>(Arrays.asList(viewer.getFilters()));
currentFilters.add(filter);
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 b7aacc6c624..1178da2e99c 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, 2014 CEA LIST and others.
+ * Copyright (c) 2010, 2014 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
@@ -10,12 +10,14 @@
* 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
+ * Christian W. Damus - bug 455075
*
*****************************************************************************/
package org.eclipse.papyrus.views.properties.modelelement;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
@@ -23,12 +25,17 @@ 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.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory;
import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider;
+import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider;
import org.eclipse.papyrus.views.properties.Activator;
import org.eclipse.papyrus.views.properties.contexts.View;
+import org.eclipse.swt.graphics.Image;
/**
* A DataSource is an object encapsulating one or more {@link ModelElement}s.
@@ -143,7 +150,44 @@ public class DataSource implements IChangeListener {
* @return
* The IStaticContentProvider corresponding to the given propertyPath
*/
- public IStaticContentProvider getContentProvider(String propertyPath) {
+ public IStaticContentProvider getContentProvider(final String propertyPath) {
+ class Delegator extends EncapsulatedContentProvider implements IDataSourceListener {
+
+ {
+ createDelegate();
+ DataSource.this.addDataSourceListener(this);
+ }
+
+ @Override
+ public void dispose() {
+ disposeDelegate();
+ DataSource.this.removeDataSourceListener(this);
+ }
+
+ private void disposeDelegate() {
+ if (encapsulated != null) {
+ encapsulated.dispose();
+ encapsulated = null;
+ }
+
+ // If I had any temporary elements, then they cannot now be relevant
+ clearTemporaryElements();
+ }
+
+ private void createDelegate() {
+ encapsulate(doGetContentProvider(propertyPath));
+ }
+
+ public void dataSourceChanged(DataSourceChangedEvent event) {
+ disposeDelegate();
+ createDelegate();
+ }
+ }
+
+ return new Delegator();
+ }
+
+ protected IStaticContentProvider doGetContentProvider(String propertyPath) {
ModelElement element = getModelElement(propertyPath);
if (element == null) {
return EmptyContentProvider.instance;
@@ -162,7 +206,89 @@ public class DataSource implements IChangeListener {
* @return
* The ILabelProvider corresponding to the given propertyPath
*/
- public ILabelProvider getLabelProvider(String propertyPath) {
+ public ILabelProvider getLabelProvider(final String propertyPath) {
+ class Delegator extends LabelProvider implements IDataSourceListener, ILabelProviderListener {
+ private ILabelProvider delegate;
+
+ private final CopyOnWriteArrayList<ILabelProviderListener> listeners = new CopyOnWriteArrayList<ILabelProviderListener>();
+
+ {
+ DataSource.this.addDataSourceListener(this);
+ }
+
+ @Override
+ public void dispose() {
+ disposeDelegate();
+ super.dispose();
+ }
+
+ private void disposeDelegate() {
+ if (delegate != null) {
+ delegate.removeListener(this);
+ delegate.dispose();
+ delegate = null;
+ }
+ }
+
+ public void dataSourceChanged(DataSourceChangedEvent event) {
+ disposeDelegate();
+ }
+
+ @Override
+ public void addListener(ILabelProviderListener listener) {
+ listeners.addIfAbsent(listener);
+ }
+
+ @Override
+ public void removeListener(ILabelProviderListener listener) {
+ listeners.remove(listener);
+ }
+
+ public void labelProviderChanged(LabelProviderChangedEvent event) {
+ if (!listeners.isEmpty()) {
+ LabelProviderChangedEvent forward = new LabelProviderChangedEvent(this, event.getElements());
+ for (ILabelProviderListener next : listeners) {
+ try {
+ next.labelProviderChanged(forward);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in label provider listener.", e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ ILabelProvider getDelegate() {
+ if (delegate == null) {
+ delegate = doGetLabelProvider(propertyPath);
+ if (delegate == null) {
+ delegate = new LabelProvider();
+ }
+ delegate.addListener(this);
+ }
+
+ return delegate;
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ return getDelegate().getImage(element);
+ }
+
+ @Override
+ public String getText(Object element) {
+ return getDelegate().getText(element);
+ }
+
+ @Override
+ public boolean isLabelProperty(Object element, String property) {
+ return getDelegate().isLabelProperty(element, property);
+ }
+ }
+
+ return new Delegator();
+ }
+
+ protected ILabelProvider doGetLabelProvider(String propertyPath) {
ModelElement element = getModelElement(propertyPath);
if (element == null) {
return null;

Back to the top