blob: 35294e85eaee4115fbdd639ad77de5a2736db0b8 [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.internal.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;
/**
* Implementation of {@link IStructuredContentProvider} and {@link ILabelProvider} that
* maintains a collection (Map, actually) of {@link IItemContentProvider}
* 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.
*/
public abstract class DelegatingContentAndLabelProvider extends BaseLabelProvider
implements IStructuredContentProvider, ILabelProvider
{
private final IItemContentProviderFactory itemContentProviderFactory;
private final IItemLabelProviderFactory itemLabelProviderFactory;
private final Map<Object, IItemContentProvider> itemContentProviders;
private final Map<Object, IItemLabelProvider> itemLabelProviders;
private StructuredViewer viewer;
protected DelegatingContentAndLabelProvider(
IItemContentProviderFactory itemContentProviderFactory) {
this(itemContentProviderFactory, null);
}
protected DelegatingContentAndLabelProvider(
IItemContentProviderFactory itemContentProviderFactory,
IItemLabelProviderFactory itemLabelProviderFactory) {
super();
this.itemContentProviderFactory = itemContentProviderFactory;
this.itemLabelProviderFactory = itemLabelProviderFactory;
this.itemContentProviders = new HashMap<Object, IItemContentProvider>();
this.itemLabelProviders = new HashMap<Object, IItemLabelProvider>();
}
protected IItemContentProvider itemContentProvider(Object item) {
IItemContentProvider 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 IItemLabelProvider itemLabelProvider(Object item) {
if (viewer == null) {
throw new IllegalStateException(
"This provider must be used as a content" +
"provider *as well as* a label provider.");
}
IItemLabelProvider 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) {
return itemLabelProvider(element).image();
}
public String getText(Object element) {
return itemLabelProvider(element).text();
}
/**
* Disposes all items
*/
public void dispose() {
// 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
*/
protected 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 viewer, Object oldInput, Object newInput) {
if (oldInput != newInput) {
dispose();
}
this.viewer = (StructuredViewer) viewer;
}
/**
* 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);
}
/**
* 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);
}
}