001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.ide;
011:
012: import java.util.ArrayList;
013: import java.util.Arrays;
014: import java.util.Iterator;
015: import java.util.List;
016:
017: import org.eclipse.core.resources.IProject;
018: import org.eclipse.core.resources.IResource;
019: import org.eclipse.core.resources.IResourceChangeEvent;
020: import org.eclipse.core.resources.IResourceChangeListener;
021: import org.eclipse.core.resources.IResourceDelta;
022: import org.eclipse.core.resources.ResourcesPlugin;
023: import org.eclipse.core.runtime.IAdaptable;
024: import org.eclipse.ui.IWorkingSet;
025: import org.eclipse.ui.IWorkingSetUpdater;
026:
027: /**
028: * A working set updater that updates resource working sets on resource deltas
029: *
030: * @since 3.2
031: */
032: public class ResourceWorkingSetUpdater implements IWorkingSetUpdater,
033: IResourceChangeListener {
034:
035: /**
036: * Utility class used to help process incoming resource deltas.
037: */
038: private static class WorkingSetDelta {
039: private IWorkingSet fWorkingSet;
040:
041: private List fElements;
042:
043: private boolean fChanged;
044:
045: /**
046: * Create a new instance of this class.
047: *
048: * @param workingSet
049: * the working set to track.
050: */
051: public WorkingSetDelta(IWorkingSet workingSet) {
052: fWorkingSet = workingSet;
053: fElements = new ArrayList(Arrays.asList(workingSet
054: .getElements()));
055: }
056:
057: /**
058: * Returns the index of this element in the list of known elements.
059: *
060: * @param element
061: * the element to search for
062: * @return the index, or -1 if unknown.
063: */
064: public int indexOf(Object element) {
065: return fElements.indexOf(element);
066: }
067:
068: /**
069: * Add a new element to the list of known elements.
070: *
071: * @param index
072: * the index at which to place the element
073: * @param element
074: * the element to set
075: */
076: public void set(int index, Object element) {
077: fElements.set(index, element);
078: fChanged = true;
079: }
080:
081: /**
082: * Remove an element from the list of known elements.
083: *
084: * @param index
085: * the index of the element to remove
086: */
087: public void remove(int index) {
088: if (fElements.remove(index) != null) {
089: fChanged = true;
090: }
091: }
092:
093: /**
094: * Process the changes to this delta and update the working set if
095: * necessary.
096: */
097: public void process() {
098: if (fChanged) {
099: fWorkingSet.setElements((IAdaptable[]) fElements
100: .toArray(new IAdaptable[fElements.size()]));
101: }
102: }
103: }
104:
105: private List fWorkingSets;
106:
107: /**
108: * Create a new instance of this updater.
109: */
110: public ResourceWorkingSetUpdater() {
111: fWorkingSets = new ArrayList();
112: ResourcesPlugin.getWorkspace().addResourceChangeListener(this ,
113: IResourceChangeEvent.POST_CHANGE);
114: }
115:
116: public void add(IWorkingSet workingSet) {
117: checkElementExistence(workingSet);
118: synchronized (fWorkingSets) {
119: fWorkingSets.add(workingSet);
120: }
121: }
122:
123: public boolean remove(IWorkingSet workingSet) {
124: boolean result;
125: synchronized (fWorkingSets) {
126: result = fWorkingSets.remove(workingSet);
127: }
128:
129: return result;
130: }
131:
132: public boolean contains(IWorkingSet workingSet) {
133: synchronized (fWorkingSets) {
134: return fWorkingSets.contains(workingSet);
135: }
136: }
137:
138: public void dispose() {
139: synchronized (fWorkingSets) {
140: fWorkingSets.clear();
141: }
142: ResourcesPlugin.getWorkspace().removeResourceChangeListener(
143: this );
144: }
145:
146: public void resourceChanged(IResourceChangeEvent event) {
147: IResourceDelta delta = event.getDelta();
148: if (delta == null) {
149: return;
150: }
151: IWorkingSet[] workingSets;
152: synchronized (fWorkingSets) {
153: workingSets = (IWorkingSet[]) fWorkingSets
154: .toArray(new IWorkingSet[fWorkingSets.size()]);
155: }
156: for (int w = 0; w < workingSets.length; w++) {
157: WorkingSetDelta workingSetDelta = new WorkingSetDelta(
158: workingSets[w]);
159: processResourceDelta(workingSetDelta, delta);
160: workingSetDelta.process();
161: }
162: }
163:
164: private void processResourceDelta(WorkingSetDelta result,
165: IResourceDelta delta) {
166: IResource resource = delta.getResource();
167: int type = resource.getType();
168: int index = result.indexOf(resource);
169: int kind = delta.getKind();
170: int flags = delta.getFlags();
171: if (kind == IResourceDelta.CHANGED && type == IResource.PROJECT
172: && index != -1) {
173: if ((flags & IResourceDelta.OPEN) != 0) {
174: result.set(index, resource);
175: }
176: }
177: if (index != -1 && kind == IResourceDelta.REMOVED) {
178: if ((flags & IResourceDelta.MOVED_TO) != 0) {
179: result.set(index, ResourcesPlugin.getWorkspace()
180: .getRoot().findMember(delta.getMovedToPath()));
181: } else {
182: result.remove(index);
183: }
184: }
185:
186: // Don't dive into closed or opened projects
187: if (projectGotClosedOrOpened(resource, kind, flags)) {
188: return;
189: }
190:
191: IResourceDelta[] children = delta.getAffectedChildren();
192: for (int i = 0; i < children.length; i++) {
193: processResourceDelta(result, children[i]);
194: }
195: }
196:
197: private boolean projectGotClosedOrOpened(IResource resource,
198: int kind, int flags) {
199: return resource.getType() == IResource.PROJECT
200: && kind == IResourceDelta.CHANGED
201: && (flags & IResourceDelta.OPEN) != 0;
202: }
203:
204: private void checkElementExistence(IWorkingSet workingSet) {
205: List elements = new ArrayList(Arrays.asList(workingSet
206: .getElements()));
207: boolean changed = false;
208: for (Iterator iter = elements.iterator(); iter.hasNext();) {
209: IAdaptable element = (IAdaptable) iter.next();
210: boolean remove = false;
211: if (element instanceof IResource) {
212: IResource resource = (IResource) element;
213: IProject project = resource.getProject();
214: remove = (project != null ? project.isOpen() : true)
215: && !resource.exists();
216: }
217: if (remove) {
218: iter.remove();
219: changed = true;
220: }
221: }
222: if (changed) {
223: workingSet.setElements((IAdaptable[]) elements
224: .toArray(new IAdaptable[elements.size()]));
225: }
226: }
227: }
|