blob: 174926fc8c714e51245874645b41ad59cefc5682 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.ui.internal.ide;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.resources.IProject;
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.ResourcesPlugin;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetUpdater;
/**
* A working set updater that updates resource working sets on resource deltas
*
* @since 3.2
*/
public class ResourceWorkingSetUpdater implements IWorkingSetUpdater,
IResourceChangeListener {
/**
* Utility class used to help process incoming resource deltas.
*/
private static class WorkingSetDelta {
private IWorkingSet fWorkingSet;
private List fElements;
private boolean fChanged;
/**
* Create a new instance of this class.
*
* @param workingSet
* the working set to track.
*/
public WorkingSetDelta(IWorkingSet workingSet) {
fWorkingSet = workingSet;
fElements = new ArrayList(Arrays.asList(workingSet.getElements()));
}
/**
* Returns the index of this element in the list of known elements.
*
* @param element
* the element to search for
* @return the index, or -1 if unknown.
*/
public int indexOf(Object element) {
return fElements.indexOf(element);
}
/**
* Add a new element to the list of known elements.
*
* @param index
* the index at which to place the element
* @param element
* the element to set
*/
public void set(int index, Object element) {
fElements.set(index, element);
fChanged = true;
}
/**
* Remove an element from the list of known elements.
*
* @param index
* the index of the element to remove
*/
public void remove(int index) {
if (fElements.remove(index) != null) {
fChanged = true;
}
}
/**
* Process the changes to this delta and update the working set if
* necessary.
*/
public void process() {
if (fChanged) {
fWorkingSet.setElements((IAdaptable[]) fElements
.toArray(new IAdaptable[fElements.size()]));
}
}
}
private List fWorkingSets;
/**
* Create a new instance of this updater.
*/
public ResourceWorkingSetUpdater() {
fWorkingSets = new ArrayList();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
IResourceChangeEvent.POST_CHANGE);
}
public void add(IWorkingSet workingSet) {
checkElementExistence(workingSet);
synchronized (fWorkingSets) {
fWorkingSets.add(workingSet);
}
}
public boolean remove(IWorkingSet workingSet) {
boolean result;
synchronized (fWorkingSets) {
result = fWorkingSets.remove(workingSet);
}
return result;
}
public boolean contains(IWorkingSet workingSet) {
synchronized (fWorkingSets) {
return fWorkingSets.contains(workingSet);
}
}
public void dispose() {
synchronized (fWorkingSets) {
fWorkingSets.clear();
}
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
}
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
if (delta == null)
return;
IWorkingSet[] workingSets;
synchronized (fWorkingSets) {
workingSets = (IWorkingSet[]) fWorkingSets
.toArray(new IWorkingSet[fWorkingSets.size()]);
}
for (int w = 0; w < workingSets.length; w++) {
WorkingSetDelta workingSetDelta = new WorkingSetDelta(
workingSets[w]);
processResourceDelta(workingSetDelta, delta);
workingSetDelta.process();
}
}
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 elements = new ArrayList(Arrays.asList(workingSet.getElements()));
boolean changed = false;
for (Iterator iter = elements.iterator(); iter.hasNext();) {
IAdaptable element = (IAdaptable) iter.next();
boolean remove = false;
if (element instanceof IResource) {
IResource resource = (IResource) element;
IProject project = resource.getProject();
remove = (project != null ? project.isOpen() : true)
&& !resource.exists();
}
if (remove) {
iter.remove();
changed = true;
}
}
if (changed) {
workingSet.setElements((IAdaptable[]) elements
.toArray(new IAdaptable[elements.size()]));
}
}
}