blob: 4603efa862a5d3dfbf91585d192526199426c140 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2004 IBM Corporation 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: IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.wst.xml.ui.internal.tabletree;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.wst.common.contentmodel.CMDocument;
import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManagerListener;
import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
import org.eclipse.wst.sse.core.AbstractAdapterFactory;
import org.eclipse.wst.sse.core.INodeAdapter;
import org.eclipse.wst.sse.core.INodeNotifier;
import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.ui.internal.Logger;
import org.eclipse.wst.xml.ui.util.SharedXMLEditorPluginImageHelper;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
public class XMLTableTreeContentProvider implements ITreeContentProvider, ITableLabelProvider, ILabelProvider, CMDocumentManagerListener {
protected ViewerNotifyingAdapterFactory viewerNotifyingAdapterFactory = new ViewerNotifyingAdapterFactory();
protected XMLTableTreePropertyDescriptorFactory propertyDescriptorFactory;
// protected ImageFactory imageFactory =
// XMLCommonUIPlugin.getInstance().getImageFactory();
protected List viewerList = new Vector();
protected TreeContentHelper treeContentHelper = new TreeContentHelper();
protected CMDocumentManager documentManager;
public XMLTableTreeContentProvider() {
}
public void getDecendantList(Object element, List list) {
Object[] children = getChildren(element);
if (children != null) {
for (int i = 0; i < children.length; i++) {
Object child = children[i];
list.add(child);
getDecendantList(child, list);
}
}
}
public void addViewer(Viewer viewer) {
viewerList.add(viewer);
}
public Object[] getChildren(Object element) {
viewerNotifyingAdapterFactory.doAdapt(element);
return treeContentHelper.getChildren(element);
}
public Object getParent(Object o) {
Object result = null;
if (o instanceof Node) {
Node node = (Node) o;
if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
result = ((Attr) node).getOwnerElement();
} else {
result = node.getParentNode();
}
}
return result;
}
public boolean hasChildren(Object element) {
viewerNotifyingAdapterFactory.doAdapt(element);
return getChildren(element).length > 0;
}
public Object[] getElements(Object element) {
viewerNotifyingAdapterFactory.doAdapt(element);
return getChildren(element);
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// remove our listeners to the old state
if (oldInput != null) {
propertyDescriptorFactory = null;
Document domDoc = (Document) oldInput;
ModelQuery mq = ModelQueryUtil.getModelQuery(domDoc);
if (mq != null) {
documentManager = mq.getCMDocumentManager();
if (documentManager != null) {
documentManager.removeListener(this);
}
}
}
if (newInput != null) {
Document domDoc = (Document) newInput;
ModelQuery mq = ModelQueryUtil.getModelQuery(domDoc);
if (mq != null) {
propertyDescriptorFactory = new XMLTableTreePropertyDescriptorFactory(mq);
documentManager = mq.getCMDocumentManager();
if (documentManager != null) {
documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, true);
documentManager.addListener(this);
}
}
}
}
public boolean isDeleted(Object element) {
return element != null;
}
//
// ILabelProvider stuff
//
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
viewerList = new Vector();
}
public Element getRootElement(Document document) {
Element rootElement = null;
for (Node childNode = document.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) {
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
rootElement = (Element) childNode;
break;
}
}
return rootElement;
}
public Image getImage(Object object) {
viewerNotifyingAdapterFactory.doAdapt(object);
Image image = null;
if (object instanceof Node) {
Node node = (Node) object;
switch (node.getNodeType()) {
case Node.ATTRIBUTE_NODE : {
image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ATTRIBUTE);
break;
}
case Node.CDATA_SECTION_NODE : {
image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_CDATASECTION);
break;
}
case Node.COMMENT_NODE : {
image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_COMMENT);
break;
}
case Node.DOCUMENT_TYPE_NODE : {
image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_DOCTYPE);
break;
}
case Node.ELEMENT_NODE : {
image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ELEMENT);
break;
}
case Node.PROCESSING_INSTRUCTION_NODE : {
image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_PROCESSINGINSTRUCTION);
break;
}
case Node.TEXT_NODE : {
image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_TXTEXT);
break;
}
case Node.ENTITY_REFERENCE_NODE : {
image = image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ENTITY_REFERENCE);
break;
}
}
// if (image != null) {
// Image markerOverlayImage =
// overlayIconManager.getOverlayImageForObject(node);
// if (markerOverlayImage != null) {
// image = imageFactory.createCompositeImage(image,
// markerOverlayImage, ImageFactory.BOTTOM_LEFT);
// }
// }
}
return image;
}
public String getText(Object object) {
viewerNotifyingAdapterFactory.doAdapt(object);
String result = null;
if (object instanceof Node) {
Node node = (Node) object;
switch (node.getNodeType()) {
case Node.ATTRIBUTE_NODE : {
result = node.getNodeName();
break;
}
case Node.DOCUMENT_TYPE_NODE : {
result = "DOCTYPE"; //$NON-NLS-1$
break;
}
case Node.ELEMENT_NODE : {
result = node.getNodeName();
break;
}
case Node.PROCESSING_INSTRUCTION_NODE : {
result = ((ProcessingInstruction) node).getTarget();
break;
}
}
}
return result != null ? result : ""; //$NON-NLS-1$
}
//
// ITableLabelProvider stuff
//
public String getColumnText(Object object, int column) {
viewerNotifyingAdapterFactory.doAdapt(object);
String result = null;
if (column == 0) {
result = getText(object);
} else if (column == 1 && object instanceof Node) {
result = treeContentHelper.getNodeValue((Node) object);
}
return result != null ? result : ""; //$NON-NLS-1$
}
public Image getColumnImage(Object object, int columnIndex) {
viewerNotifyingAdapterFactory.doAdapt(object);
return (columnIndex == 0) ? getImage(object) : null;
}
public boolean isLabelProperty(Object object, String property) {
return false;
}
public void removeListener(ILabelProviderListener listener) {
}
// There is only 1 adapter associated with this factory. This single
// adapter gets added
// to the adapter lists of many nodes.
public class ViewerNotifyingAdapterFactory extends AbstractAdapterFactory {
protected ViewerNotifyingAdapter viewerNotifyingAdapter = new ViewerNotifyingAdapter();
protected INodeAdapter createAdapter(INodeNotifier target) {
return viewerNotifyingAdapter;
}
protected ViewerNotifyingAdapter doAdapt(Object object) {
ViewerNotifyingAdapter result = null;
if (object instanceof INodeNotifier) {
result = (ViewerNotifyingAdapter) adapt((INodeNotifier) object);
}
return result;
}
}
public class ViewerNotifyingAdapter implements INodeAdapter {
public boolean isAdapterForType(Object type) {
return type.equals(viewerNotifyingAdapterFactory);
}
public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
switch (eventType) {
//case INodeNotifier.ADD: // ignore
//case INodeNotifier.REMOVE: // ignore
case INodeNotifier.CHANGE :
case INodeNotifier.STRUCTURE_CHANGED :
case INodeNotifier.CONTENT_CHANGED : {
Node node = (Node) notifier;
if (node.getNodeType() == Node.ELEMENT_NODE || node.getNodeType() == Node.DOCUMENT_NODE) {
for (Iterator i = viewerList.iterator(); i.hasNext();) {
Viewer viewer = (Viewer) i.next();
if (viewer instanceof StructuredViewer) {
((StructuredViewer) viewer).refresh(node);
} else {
// todo... consider doing a time delayed
// refresh here!!
viewer.refresh();
}
}
}
break;
}
}
}
}
// the following methods handle filtering aspects of the viewer
//
//
public boolean isIgnorableText(Node node) {
boolean result = false;
try {
if (node.getNodeType() == Node.TEXT_NODE) {
String data = ((Text) node).getData();
result = (data == null || data.trim().length() == 0);
}
} catch (Exception e) {
Logger.logException(e);
}
return result;
}
public static Text getHiddenChildTextNode(Node node) {
return null;
}
// CMDocumentManagerListener
//
public void cacheCleared(CMDocumentCache cache) {
doDelayedRefreshForViewers();
}
public void cacheUpdated(CMDocumentCache cache, final String uri, int oldStatus, int newStatus, CMDocument cmDocument) {
if (newStatus == CMDocumentCache.STATUS_LOADED || newStatus == CMDocumentCache.STATUS_ERROR) {
doDelayedRefreshForViewers();
}
}
public void propertyChanged(CMDocumentManager cmDocumentManager, String propertyName) {
if (cmDocumentManager.getPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD)) {
doDelayedRefreshForViewers();
}
}
protected void doDelayedRefreshForViewers() {
List list = new Vector();
list.addAll(viewerList);
for (Iterator i = list.iterator(); i.hasNext();) {
final Viewer viewer = (Viewer) i.next();
Control control = viewer.getControl();
Runnable runnable = new Runnable() {
public void run() {
viewer.refresh();
}
};
// we need to ensure that this is run via 'asyncExec' since these
// notifications can come from a non-ui thread
control.getDisplay().asyncExec(runnable);
}
}
}