| /******************************************************************************* |
| * Copyright (c) 2000, 2017 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 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.ui.workingsets; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceDelta; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.ElementChangedEvent; |
| import org.eclipse.dltk.core.IElementChangedListener; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IModelElementDelta; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.ui.IWorkingSet; |
| import org.eclipse.ui.IWorkingSetUpdater; |
| |
| public class ScriptWorkingSetUpdater implements IWorkingSetUpdater, IElementChangedListener { |
| |
| private List<IWorkingSet> fWorkingSets; |
| |
| private static class WorkingSetDelta { |
| private IWorkingSet fWorkingSet; |
| private List<IAdaptable> fElements; |
| private boolean fChanged; |
| public WorkingSetDelta(IWorkingSet workingSet) { |
| fWorkingSet= workingSet; |
| fElements = new ArrayList<IAdaptable>( |
| Arrays.asList(workingSet.getElements())); |
| } |
| public int indexOf(Object element) { |
| return fElements.indexOf(element); |
| } |
| |
| public void set(int index, IAdaptable element) { |
| fElements.set(index, element); |
| fChanged= true; |
| } |
| public void remove(int index) { |
| if (fElements.remove(index) != null) { |
| fChanged= true; |
| } |
| } |
| public void process() { |
| if (fChanged) { |
| fWorkingSet.setElements( |
| fElements.toArray(new IAdaptable[fElements.size()])); |
| } |
| } |
| } |
| |
| public ScriptWorkingSetUpdater() { |
| fWorkingSets = new ArrayList<IWorkingSet>(); |
| DLTKCore.addElementChangedListener(this); |
| } |
| |
| @Override |
| public void add(IWorkingSet workingSet) { |
| checkElementExistence(workingSet); |
| synchronized (fWorkingSets) { |
| fWorkingSets.add(workingSet); |
| } |
| } |
| |
| @Override |
| public boolean remove(IWorkingSet workingSet) { |
| boolean result; |
| synchronized(fWorkingSets) { |
| result= fWorkingSets.remove(workingSet); |
| } |
| return result; |
| } |
| |
| @Override |
| public boolean contains(IWorkingSet workingSet) { |
| synchronized(fWorkingSets) { |
| return fWorkingSets.contains(workingSet); |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| synchronized(fWorkingSets) { |
| fWorkingSets.clear(); |
| } |
| DLTKCore.removeElementChangedListener(this); |
| } |
| |
| @Override |
| public void elementChanged(ElementChangedEvent event) { |
| IWorkingSet[] workingSets; |
| synchronized(fWorkingSets) { |
| workingSets = fWorkingSets |
| .toArray(new IWorkingSet[fWorkingSets.size()]); |
| } |
| for (int w= 0; w < workingSets.length; w++) { |
| WorkingSetDelta workingSetDelta= new WorkingSetDelta(workingSets[w]); |
| processScriptDelta(workingSetDelta, event.getDelta()); |
| IResourceDelta[] resourceDeltas= event.getDelta().getResourceDeltas(); |
| if (resourceDeltas != null) { |
| for (int r= 0; r < resourceDeltas.length; r++) { |
| processResourceDelta(workingSetDelta, resourceDeltas[r]); |
| } |
| } |
| workingSetDelta.process(); |
| } |
| } |
| |
| private void processScriptDelta(WorkingSetDelta result, IModelElementDelta delta) { |
| IModelElement jElement= delta.getElement(); |
| int index= result.indexOf(jElement); |
| int type= jElement.getElementType(); |
| int kind= delta.getKind(); |
| int flags= delta.getFlags(); |
| if (type == IModelElement.SCRIPT_PROJECT && kind == IModelElementDelta.CHANGED) { |
| if (index != -1 && (flags & IModelElementDelta.F_CLOSED) != 0) { |
| result.set(index, ((IScriptProject)jElement).getProject()); |
| } else if ((flags & IModelElementDelta.F_OPENED) != 0) { |
| index= result.indexOf(((IScriptProject)jElement).getProject()); |
| if (index != -1) |
| result.set(index, jElement); |
| } |
| } |
| if (index != -1) { |
| if (kind == IModelElementDelta.REMOVED) { |
| if ((flags & IModelElementDelta.F_MOVED_TO) != 0) { |
| result.set(index, delta.getMovedToElement()); |
| } else { |
| result.remove(index); |
| } |
| } |
| } |
| IResourceDelta[] resourceDeltas= delta.getResourceDeltas(); |
| if (resourceDeltas != null) { |
| for (int i= 0; i < resourceDeltas.length; i++) { |
| processResourceDelta(result, resourceDeltas[i]); |
| } |
| } |
| IModelElementDelta[] children= delta.getAffectedChildren(); |
| for (int i= 0; i < children.length; i++) { |
| processScriptDelta(result, children[i]); |
| } |
| } |
| |
| private void processResourceDelta(WorkingSetDelta result, IResourceDelta delta) { |
| IResource resource= delta.getResource(); |
| int type= resource.getType(); |
| int index= result.indexOf(resource); |
| int kind= delta.getKind(); |
| int flags= delta.getFlags(); |
| if (kind == IResourceDelta.CHANGED && type == IResource.PROJECT && index != -1) { |
| if ((flags & IResourceDelta.OPEN) != 0) { |
| result.set(index, resource); |
| } |
| } |
| if (index != -1 && kind == IResourceDelta.REMOVED) { |
| if ((flags & IResourceDelta.MOVED_TO) != 0) { |
| result.set(index, |
| ResourcesPlugin.getWorkspace().getRoot().findMember(delta.getMovedToPath())); |
| } else { |
| result.remove(index); |
| } |
| } |
| |
| // Don't dive into closed or opened projects |
| if (projectGotClosedOrOpened(resource, kind, flags)) |
| return; |
| |
| IResourceDelta[] children= delta.getAffectedChildren(); |
| for (int i= 0; i < children.length; i++) { |
| processResourceDelta(result, children[i]); |
| } |
| } |
| |
| private boolean projectGotClosedOrOpened(IResource resource, int kind, int flags) { |
| return resource.getType() == IResource.PROJECT |
| && kind == IResourceDelta.CHANGED |
| && (flags & IResourceDelta.OPEN) != 0; |
| } |
| |
| private void checkElementExistence(IWorkingSet workingSet) { |
| List<IAdaptable> elements = new ArrayList<IAdaptable>( |
| Arrays.asList(workingSet.getElements())); |
| boolean changed= false; |
| for (Iterator<IAdaptable> iter = elements.iterator(); iter.hasNext();) { |
| IAdaptable element = iter.next(); |
| boolean remove= false; |
| if (element instanceof IModelElement) { |
| IModelElement jElement= (IModelElement)element; |
| // If we have directly a project then remove it when it |
| // doesn't exist anymore. However if we have a sub element |
| // under a project only remove the element if the parent |
| // project is open. Otherwise we would remove all elements |
| // in closed projects. |
| if (jElement instanceof IScriptProject) { |
| remove= !jElement.exists(); |
| } else { |
| IProject project= jElement.getScriptProject().getProject(); |
| remove= project.isOpen() && !jElement.exists(); |
| } |
| } else if (element instanceof IResource) { |
| IResource resource= (IResource)element; |
| // See comments above |
| if (resource instanceof IProject) { |
| remove= !resource.exists(); |
| } else { |
| IProject project= resource.getProject(); |
| remove= (project != null ? project.isOpen() : true) && !resource.exists(); |
| } |
| } |
| if (remove) { |
| iter.remove(); |
| changed= true; |
| } |
| } |
| if (changed) { |
| workingSet.setElements( |
| elements.toArray(new IAdaptable[elements.size()])); |
| } |
| } |
| } |