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