package org.erlide.ui.navigator; import java.util.Collection; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.navigator.SaveablesProvider; import org.eclipse.ui.progress.UIJob; import org.erlide.engine.ErlangEngine; import org.erlide.engine.model.ErlModelException; import org.erlide.engine.model.IErlElement; import org.erlide.engine.model.IParent; import org.erlide.engine.model.root.IErlModel; import org.erlide.engine.model.root.IErlModelChangeListener; import org.erlide.engine.model.root.IErlModule; import org.erlide.engine.model.root.IErlProject; import org.erlide.engine.model.root.IOpenable; import org.erlide.util.ErlLogger; public class ErlangFileContentProvider implements ITreeContentProvider, IResourceChangeListener, IResourceDeltaVisitor, IErlModelChangeListener, IAdaptable { private static final Object[] NO_CHILDREN = new Object[0]; StructuredViewer viewer; /** * Create the PropertiesContentProvider instance. * * Adds the content provider as a resource change listener to track changes on disk. * */ public ErlangFileContentProvider() { ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); final IErlModel mdl = ErlangEngine.getInstance().getModel(); mdl.addModelChangeListener(this); } /** * Return the model elements for a *.erl IFile or NO_CHILDREN for otherwise. */ @Override public Object[] getChildren(final Object parentElement0) { Object parentElement = parentElement0; try { if (parentElement instanceof IFile) { parentElement = ErlangEngine.getInstance().getModel() .findModule((IFile) parentElement); } if (parentElement instanceof IOpenable) { final IOpenable openable = (IOpenable) parentElement; openable.open(null); } if (parentElement instanceof IParent) { final IParent parent = (IParent) parentElement; final Collection<IErlElement> children = parent.getChildren(); return children.toArray(); } } catch (final ErlModelException e) { ErlLogger.warn(e); } return NO_CHILDREN; } /** * Load the model from the given file, if possible. * * @param modelFile * The IFile which contains the persisted model */ @Override public Object getParent(final Object element) { if (element instanceof IErlElement) { final IErlElement elt = (IErlElement) element; final IParent parent = elt.getParent(); if (parent instanceof IErlModule || parent instanceof IErlProject) { final IErlElement e = (IErlElement) parent; return e.getCorrespondingResource(); } } return null; } @Override public boolean hasChildren(final Object element) { if (element instanceof IFile || element instanceof IErlModule) { // it was too slow to open all modules to find out; // empty modules aren't widely used anyway :-) return true; } else if (element instanceof IParent) { final IParent parent = (IParent) element; return parent.hasChildren(); } return false; } @Override public Object[] getElements(final Object inputElement) { return getChildren(inputElement); } @Override public void dispose() { ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); ErlangEngine.getInstance().getModel().removeModelChangeListener(this); } @Override public void inputChanged(final Viewer theViewer, final Object oldInput, final Object newInput) { if (theViewer instanceof StructuredViewer) { viewer = (StructuredViewer) theViewer; } else { viewer = null; } } @Override public void resourceChanged(final IResourceChangeEvent event) { final IResourceDelta delta = event.getDelta(); try { if (delta != null) { // ErlLogger.debug("change " + event.toString()); delta.accept(this); } } catch (final CoreException e) { ErlLogger.warn(e); } } @Override public boolean visit(final IResourceDelta delta) { final IResource source = delta.getResource(); switch (source.getType()) { case IResource.ROOT: case IResource.PROJECT: case IResource.FOLDER: return true; case IResource.FILE: final IFile file = (IFile) source; // if (ErlideUtil.isErlangFileContentFileName(file.getName())) { doRefresh(file); // } return false; } return false; } private void doRefresh(final IFile file) { // Commented out because it may cause problems with too many updates. // TODO Investigate further! final String title = "Update Erlang Model in CommonViewer: " + file.getName(); if (viewer == null) { return; } new UIJob(title) { @Override public IStatus runInUIThread(final IProgressMonitor monitor) { if (viewer != null && !viewer.getControl().isDisposed()) { viewer.refresh(file); // viewer.update(file, null); } return Status.OK_STATUS; } }.schedule(); } @Override public void elementChanged(final IErlElement element) { if (element instanceof IErlModule) { final IErlModule m = (IErlModule) element; final IResource r = m.getResource(); if (r instanceof IFile) { doRefresh((IFile) r); } } } @Override public Object getAdapter(@SuppressWarnings("rawtypes") final Class required) { if (SaveablesProvider.class.equals(required)) { // TODO return something useful return null; } return null; } }