| package org.eclipse.wst.xml.ui.internal.projection; |
| |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.source.projection.IProjectionListener; |
| import org.eclipse.jface.text.source.projection.ProjectionViewer; |
| import org.eclipse.wst.sse.core.internal.PropagatingAdapter; |
| import org.eclipse.wst.sse.core.internal.model.FactoryRegistry; |
| import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier; |
| import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; |
| import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; |
| import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager; |
| import org.eclipse.wst.sse.ui.internal.projection.IStructuredTextFoldingProvider; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| |
| /** |
| * Updates the projection model of a structured model for XML. |
| */ |
| public class StructuredTextFoldingProviderXML implements IStructuredTextFoldingProvider, IProjectionListener { |
| private final static boolean debugProjectionPerf = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.xml.ui/projectionperf")); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| private IDocument fDocument; |
| private ProjectionViewer fViewer; |
| |
| /** |
| * Adds an adapter to node and its children |
| * |
| * @param node |
| * @param level |
| */ |
| private void addAdapterToNodeAndChildren(Node node, int level) { |
| if (node instanceof INodeNotifier) { |
| INodeNotifier notifier = (INodeNotifier) node; |
| |
| // try and get the adapter for the current node and update the |
| // adapter with projection information |
| ProjectionModelNodeAdapterXML adapter = (ProjectionModelNodeAdapterXML) notifier.getExistingAdapter(ProjectionModelNodeAdapterXML.class); |
| if (adapter != null) { |
| adapter.updateAdapter(node); |
| } |
| else { |
| // just call getadapter so the adapter is created and |
| // automatically initialized |
| notifier.getAdapterFor(ProjectionModelNodeAdapterXML.class); |
| } |
| |
| Node nextChild = node.getFirstChild(); |
| while (nextChild != null) { |
| Node childNode = nextChild; |
| nextChild = childNode.getNextSibling(); |
| |
| addAdapterToNodeAndChildren(childNode, level + 1); |
| } |
| } |
| } |
| |
| /** |
| * Goes through every node and adds an adapter onto each for tracking |
| * purposes |
| */ |
| private void addAllAdapters() { |
| long start = System.currentTimeMillis(); |
| |
| IStructuredModel sModel = null; |
| try { |
| sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument); |
| if (sModel != null) { |
| int startOffset = 0; |
| IndexedRegion startNode = sModel.getIndexedRegion(startOffset); |
| if (startNode instanceof Node) { |
| int level = 0; |
| Node nextSibling = (Node) startNode; |
| while (nextSibling != null) { |
| Node currentNode = nextSibling; |
| nextSibling = currentNode.getNextSibling(); |
| |
| addAdapterToNodeAndChildren(currentNode, level); |
| } |
| } |
| } |
| } |
| finally { |
| if (sModel != null) { |
| sModel.releaseFromRead(); |
| } |
| } |
| |
| long end = System.currentTimeMillis(); |
| if (debugProjectionPerf) |
| System.out.println("StructuredTextFoldingProviderXML.addAllAdapters: " + (end - start)); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Get the ProjectionModelNodeAdapterFactoryXML to use with this provider. |
| * |
| * @return ProjectionModelNodeAdapterFactoryXML |
| */ |
| private ProjectionModelNodeAdapterFactoryXML getAdapterFactory(boolean createIfNeeded) { |
| long start = System.currentTimeMillis(); |
| |
| ProjectionModelNodeAdapterFactoryXML factory = null; |
| IStructuredModel sModel = null; |
| try { |
| sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument); |
| if (sModel != null) { |
| FactoryRegistry factoryRegistry = sModel.getFactoryRegistry(); |
| |
| // getting the projectionmodelnodeadapter for the first time |
| // so do some initializing |
| if (!factoryRegistry.contains(ProjectionModelNodeAdapterXML.class) && createIfNeeded) { |
| ProjectionModelNodeAdapterFactoryXML newFactory = new ProjectionModelNodeAdapterFactoryXML(); |
| |
| // add factory to factory registry |
| factoryRegistry.addFactory(newFactory); |
| |
| // add factory to propogating adapter |
| IDOMModel domModel = (IDOMModel) sModel; |
| Document document = domModel.getDocument(); |
| PropagatingAdapter propagatingAdapter = (PropagatingAdapter) ((INodeNotifier) document).getAdapterFor(PropagatingAdapter.class); |
| if (propagatingAdapter != null) { |
| propagatingAdapter.addAdaptOnCreateFactory(newFactory); |
| } |
| } |
| |
| // try and get the factory |
| factory = (ProjectionModelNodeAdapterFactoryXML) factoryRegistry.getFactoryFor(ProjectionModelNodeAdapterXML.class); |
| } |
| } |
| finally { |
| if (sModel != null) |
| sModel.releaseFromRead(); |
| } |
| |
| long end = System.currentTimeMillis(); |
| if (debugProjectionPerf) |
| System.out.println("StructuredTextFoldingProviderXML.getAdapterFactory: " + (end - start)); //$NON-NLS-1$ |
| return factory; |
| } |
| |
| /** |
| * Initialize this provider with the correct document. Assumes projection |
| * is enabled. (otherwise, only install would have been called) |
| */ |
| public void initialize() { |
| if (!isInstalled()) |
| return; |
| |
| // set projection viewer to null on old document's adapter factory |
| ProjectionModelNodeAdapterFactoryXML factory = getAdapterFactory(false); |
| if (factory != null) { |
| factory.setProjectionViewer(null); |
| } |
| // clear out all annotations |
| if (fViewer.getProjectionAnnotationModel() != null) |
| fViewer.getProjectionAnnotationModel().removeAllAnnotations(); |
| |
| fDocument = fViewer.getDocument(); |
| |
| if (fDocument != null) { |
| // set projection viewer on new document's adapter factory |
| factory = getAdapterFactory(true); |
| if (factory != null) { |
| factory.setProjectionViewer(fViewer); |
| } |
| |
| addAllAdapters(); |
| } |
| } |
| |
| /** |
| * Associate a ProjectionViewer with this IStructuredTextFoldingProvider |
| * |
| * @param viewer |
| */ |
| public void install(ProjectionViewer viewer) { |
| // uninstall before trying to install new viewer |
| if (isInstalled()) { |
| uninstall(); |
| } |
| fViewer = viewer; |
| fViewer.addProjectionListener(this); |
| } |
| |
| private boolean isInstalled() { |
| return fViewer != null; |
| } |
| |
| public void projectionDisabled() { |
| ProjectionModelNodeAdapterFactoryXML factory = getAdapterFactory(false); |
| if (factory != null) { |
| factory.setProjectionViewer(null); |
| } |
| |
| fDocument = null; |
| } |
| |
| public void projectionEnabled() { |
| initialize(); |
| } |
| |
| /** |
| * Disconnect this IStructuredTextFoldingProvider from projection viewer |
| */ |
| public void uninstall() { |
| if (isInstalled()) { |
| projectionDisabled(); |
| |
| fViewer.removeProjectionListener(this); |
| fViewer = null; |
| } |
| } |
| } |