blob: 2b6b959bc28e2ef9fd869b2db4670b778118ebfe [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Oracle. 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:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.ui.jface;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jface.viewers.BaseLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.navigator.IDescriptionProvider;
/**
* Implementation of {@link IStructuredContentProvider} and {@link ILabelProvider} that
* maintains a collection (Map, actually) of {@link ItemContentProvider}
* delegates that perform the function of providing content and label information
* for each represented item
*
* NB: This class, if used as a label provider *MUST* be used as a content provider
* for the same viewer. It may be used as a content provider with a different
* label provider, however.
*
* Provisional API: This class is part of an interim API that is still
* under development and expected to change significantly before reaching
* stability. It is available at this early stage to solicit feedback from
* pioneering adopters on the understanding that any code that uses this API
* will almost certainly be broken (repeatedly) as the API evolves.
*/
public abstract class DelegatingContentAndLabelProvider
extends BaseLabelProvider
implements IStructuredContentProvider, ILabelProvider, IDescriptionProvider
{
private final ItemContentProviderFactory itemContentProviderFactory;
private final ItemLabelProviderFactory itemLabelProviderFactory;
private final Map<Object, ItemContentProvider> itemContentProviders;
private final Map<Object, ItemLabelProvider> itemLabelProviders;
StructuredViewer viewer;
protected DelegatingContentAndLabelProvider(
ItemContentProviderFactory itemContentProviderFactory) {
this(itemContentProviderFactory, null);
}
protected DelegatingContentAndLabelProvider(
ItemContentProviderFactory itemContentProviderFactory,
ItemLabelProviderFactory itemLabelProviderFactory) {
super();
this.itemContentProviderFactory = itemContentProviderFactory;
this.itemLabelProviderFactory = itemLabelProviderFactory;
this.itemContentProviders = new HashMap<Object, ItemContentProvider>();
this.itemLabelProviders = new HashMap<Object, ItemLabelProvider>();
}
protected ItemContentProvider itemContentProvider(Object item) {
ItemContentProvider itemContentProvider = itemContentProviders.get(item);
if (itemContentProvider != null) {
return itemContentProvider;
}
itemContentProvider = itemContentProviderFactory.buildItemContentProvider(item, this);
if (itemContentProvider == null) {
return null;
}
itemContentProviders.put(item, itemContentProvider);
return itemContentProvider;
}
protected ItemLabelProvider itemLabelProvider(Object item) {
if (viewer == null) {
throw new IllegalStateException(
"This provider must be used as a content" +
"provider *as well as* a label provider.");
}
ItemLabelProvider itemLabelProvider = itemLabelProviders.get(item);
if (itemLabelProvider != null) {
return itemLabelProvider;
}
itemLabelProvider = itemLabelProviderFactory.buildItemLabelProvider(item, this);
if (itemLabelProvider == null) {
return null;
}
itemLabelProviders.put(item, itemLabelProvider);
return itemLabelProvider;
}
public Object[] getElements(Object inputElement) {
return itemContentProvider(inputElement).getElements();
}
public Image getImage(Object element) {
ItemLabelProvider provider = itemLabelProvider(element);
return (provider == null) ? null :provider.getImage();
}
public String getText(Object element) {
ItemLabelProvider provider = itemLabelProvider(element);
return (provider == null) ? null : provider.getText();
}
public String getDescription(Object element) {
ItemLabelProvider provider = itemLabelProvider(element);
return (provider == null) ? null : provider.getDescription();
}
/**
* Disposes all items
*/
@Override
public void dispose() {
disposeProviders();
super.dispose();
}
protected void disposeProviders() {
// coded this way to allow some item providers to dispose of their child
// elements without disrupting the entire process
while (! itemContentProviders.isEmpty()) {
dispose(itemContentProviders.keySet().iterator().next());
}
// this catches any items that weren't disposed from the content providers,
// though there most likely won't be any items represented here that
// haven't already been disposed
while (! itemLabelProviders.isEmpty()) {
dispose(itemLabelProviders.keySet().iterator().next());
}
}
/**
* Disposes item
*/
public void dispose(Object item) {
if (itemContentProviders.containsKey(item)) {
itemContentProviders.get(item).dispose();
itemContentProviders.remove(item);
}
if (itemLabelProviders.containsKey(item)) {
itemLabelProviders.get(item).dispose();
itemLabelProviders.remove(item);
}
}
public void inputChanged(Viewer structuredViewer, Object oldInput, Object newInput) {
if (oldInput != newInput) {
disposeProviders();
}
this.viewer = (StructuredViewer) structuredViewer;
}
/**
* Update the content for the given item
*/
public void updateContent(final Object item) {
Runnable runnable = new Runnable() {
public void run() {
if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
viewer.refresh(item);
}
}
};
viewer.getControl().getDisplay().asyncExec(runnable);
}
// open up visibility a bit for inner classes
@Override
protected void fireLabelProviderChanged(LabelProviderChangedEvent event) {
super.fireLabelProviderChanged(event);
}
/**
* Update the label for the given item
*/
public void updateLabel(final Object item) {
Runnable runnable = new Runnable() {
public void run() {
if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
fireLabelProviderChanged(new LabelProviderChangedEvent(DelegatingContentAndLabelProvider.this, item));
}
}
};
viewer.getControl().getDisplay().asyncExec(runnable);
}
}