| /***************************************************************************** |
| * 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); |
| } |
| } |
| } |