blob: 0957cfb96f385616a16cb195d503a0411826b252 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2015 Wind River Systems, Inc. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.ui.controls;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.tcf.te.core.interfaces.IConnectable;
import org.eclipse.tcf.te.core.interfaces.IPropertyChangeProvider;
import org.eclipse.tcf.te.runtime.model.MessageModelNode;
import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode;
import org.eclipse.tcf.te.ui.trees.CommonViewerListener;
import org.eclipse.tcf.te.ui.trees.Pending;
/**
* The base tree content provider that defines several default methods.
*/
public abstract class TreeContentProvider implements ITreeContentProvider {
/**
* Static reference to the return value representing no elements.
*/
protected final static Object[] NO_ELEMENTS = new Object[0];
// The listener to refresh the common viewer when properties change.
protected CommonViewerListener commonViewerListener;
// The viewer inputs that have been added a property change listener.
private Set<IPropertyChangeProvider> providers = Collections.synchronizedSet(new HashSet<IPropertyChangeProvider>());
// The viewer
protected TreeViewer viewer;
// The pending nodes and their direct parents.
private Map<Object, Pending> pendings;
// The target's peer model.
private IPeerNode peerNode;
/**
* Create a tree content provider.
*/
public TreeContentProvider() {
pendings = new HashMap<Object, Pending>();
}
/**
* Get the pending node for the specified parent.
* If it exists, then return it. If not, create one
* and save it and return it.
*/
protected Pending getPending(Object parent) {
Pending pending = pendings.get(parent);
if(pending == null && viewer != null) {
pending = new Pending(viewer);
pendings.put(parent, pending);
}
return pending;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
@Override
public void dispose() {
for(IPropertyChangeProvider provider : providers) {
provider.removePropertyChangeListener(commonViewerListener);
}
commonViewerListener.cancel();
providers.clear();
pendings.clear();
}
/**
* Get the filtered children of the parent using the
* filters registered in the viewer.
*
* @param parent The parent element.
* @return The children after filtering.
*/
private Object[] getFilteredChildren(Object parent) {
Object[] result = getChildren(parent);
if (viewer != null) {
ViewerFilter[] filters = viewer.getFilters();
if (filters != null) {
for (ViewerFilter filter : filters) {
Object[] filteredResult = filter.filter(viewer, parent, result);
result = filteredResult;
}
}
}
return result;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
*/
@Override
public Object[] getChildren(Object parentElement) {
Assert.isNotNull(parentElement);
if (parentElement instanceof IAdaptable) {
IAdaptable adaptable = (IAdaptable) parentElement;
IPropertyChangeProvider provider = (IPropertyChangeProvider) adaptable.getAdapter(IPropertyChangeProvider.class);
if (provider != null) {
installPropertyChangeListener(provider);
}
}
return NO_ELEMENTS;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if (commonViewerListener != null) {
for (IPropertyChangeProvider provider : providers) {
provider.removePropertyChangeListener(commonViewerListener);
}
}
Assert.isTrue(viewer instanceof TreeViewer);
this.viewer = (TreeViewer) viewer;
this.commonViewerListener = new CommonViewerListener(this.viewer, this);
peerNode = getPeerNode(newInput);
for (IPropertyChangeProvider provider : providers) {
provider.addPropertyChangeListener(commonViewerListener);
}
}
protected IPeerNode getPeerNode(Object input) {
IPeerNode peerNode = input instanceof IPeerNode ? (IPeerNode)input : null;
if (peerNode == null && input instanceof IAdaptable) {
peerNode = (IPeerNode)((IAdaptable)input).getAdapter(IPeerNode.class);
}
return peerNode;
}
/**
* Install a property change listener to the specified element.
*
* @param provider The element node.
*/
private void installPropertyChangeListener(IPropertyChangeProvider provider) {
if (provider != null && !providers.contains(provider)) {
if (commonViewerListener != null) {
provider.addPropertyChangeListener(commonViewerListener);
}
providers.add(provider);
}
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
@Override
public boolean hasChildren(Object element) {
Object[] children = getFilteredChildren(element);
return children != null && children.length > 0;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#getElements(java.lang.Object)
*/
@Override
public Object[] getElements(Object inputElement) {
if (peerNode != null && peerNode.getConnectState() == IConnectable.STATE_CONNECTED) {
return getChildren(inputElement);
}
String message = null;
if (peerNode != null) {
if (peerNode.getConnectState() == IConnectable.STATE_CONNECTION_LOST ||
peerNode.getConnectState() == IConnectable.STATE_CONNECTION_RECOVERING) {
message = Messages.getStringDelegated(peerNode, "FileSystem_ContentProvider_connectionLost"); //$NON-NLS-1$
}
if (message == null) {
message = Messages.getStringDelegated(peerNode, "FileSystem_ContentProvider_notConnected"); //$NON-NLS-1$
}
}
return new Object[] { new MessageModelNode(message != null ? message : Messages.ContentProvider_notConnected, IStatus.INFO, false) };
}
}