KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > model > WorkbenchContentProvider


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.model;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collection JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17 import org.eclipse.core.resources.IContainer;
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.core.resources.IResourceChangeEvent;
20 import org.eclipse.core.resources.IResourceChangeListener;
21 import org.eclipse.core.resources.IResourceDelta;
22 import org.eclipse.core.resources.IWorkspace;
23 import org.eclipse.jface.viewers.AbstractTreeViewer;
24 import org.eclipse.jface.viewers.StructuredViewer;
25 import org.eclipse.jface.viewers.Viewer;
26 import org.eclipse.swt.widgets.Control;
27
28 /**
29  * Tree content provider for resource objects that can be adapted to the
30  * interface {@link org.eclipse.ui.model.IWorkbenchAdapter IWorkbenchAdapter}.
31  * This provider will listen for resource changes within the workspace and
32  * update the viewer as necessary.
33  * <p>
34  * This class may be instantiated, or subclassed by clients.
35  * </p>
36  */

37 public class WorkbenchContentProvider extends BaseWorkbenchContentProvider
38         implements IResourceChangeListener {
39     private Viewer viewer;
40
41     /**
42      * Creates the resource content provider.
43      */

44     public WorkbenchContentProvider() {
45         super();
46     }
47
48     /*
49      * (non-Javadoc) Method declared on IContentProvider.
50      */

51     public void dispose() {
52         if (viewer != null) {
53             IWorkspace workspace = null;
54             Object JavaDoc obj = viewer.getInput();
55             if (obj instanceof IWorkspace) {
56                 workspace = (IWorkspace) obj;
57             } else if (obj instanceof IContainer) {
58                 workspace = ((IContainer) obj).getWorkspace();
59             }
60             if (workspace != null) {
61                 workspace.removeResourceChangeListener(this);
62             }
63         }
64
65         super.dispose();
66     }
67
68     /*
69      * (non-Javadoc) Method declared on IContentProvider.
70      */

71     public void inputChanged(Viewer viewer, Object JavaDoc oldInput, Object JavaDoc newInput) {
72         super.inputChanged(viewer, oldInput, newInput);
73
74         this.viewer = viewer;
75         IWorkspace oldWorkspace = null;
76         IWorkspace newWorkspace = null;
77
78         if (oldInput instanceof IWorkspace) {
79             oldWorkspace = (IWorkspace) oldInput;
80         } else if (oldInput instanceof IContainer) {
81             oldWorkspace = ((IContainer) oldInput).getWorkspace();
82         }
83
84         if (newInput instanceof IWorkspace) {
85             newWorkspace = (IWorkspace) newInput;
86         } else if (newInput instanceof IContainer) {
87             newWorkspace = ((IContainer) newInput).getWorkspace();
88         }
89
90         if (oldWorkspace != newWorkspace) {
91             if (oldWorkspace != null) {
92                 oldWorkspace.removeResourceChangeListener(this);
93             }
94             if (newWorkspace != null) {
95                 newWorkspace.addResourceChangeListener(this,
96                         IResourceChangeEvent.POST_CHANGE);
97             }
98         }
99     }
100
101     /*
102      * (non-Javadoc) Method declared on IResourceChangeListener.
103      */

104     public final void resourceChanged(final IResourceChangeEvent event) {
105
106         processDelta(event.getDelta());
107
108     }
109
110     /**
111      * Process the resource delta.
112      *
113      * @param delta
114      */

115     protected void processDelta(IResourceDelta delta) {
116
117         Control ctrl = viewer.getControl();
118         if (ctrl == null || ctrl.isDisposed()) {
119             return;
120         }
121         
122         
123         final Collection JavaDoc runnables = new ArrayList JavaDoc();
124         processDelta(delta, runnables);
125
126         if (runnables.isEmpty()) {
127             return;
128         }
129
130         //Are we in the UIThread? If so spin it until we are done
131
if (ctrl.getDisplay().getThread() == Thread.currentThread()) {
132             runUpdates(runnables);
133         } else {
134             ctrl.getDisplay().asyncExec(new Runnable JavaDoc(){
135                 /* (non-Javadoc)
136                  * @see java.lang.Runnable#run()
137                  */

138                 public void run() {
139                     //Abort if this happens after disposes
140
Control ctrl = viewer.getControl();
141                     if (ctrl == null || ctrl.isDisposed()) {
142                         return;
143                     }
144                     
145                     runUpdates(runnables);
146                 }
147             });
148         }
149
150     }
151
152     /**
153      * Run all of the runnables that are the widget updates
154      * @param runnables
155      */

156     private void runUpdates(Collection JavaDoc runnables) {
157         Iterator JavaDoc runnableIterator = runnables.iterator();
158         while(runnableIterator.hasNext()){
159             ((Runnable JavaDoc)runnableIterator.next()).run();
160         }
161         
162     }
163
164     /**
165      * Process a resource delta. Add any runnables
166      */

167     private void processDelta(IResourceDelta delta, Collection JavaDoc runnables) {
168         //he widget may have been destroyed
169
// by the time this is run. Check for this and do nothing if so.
170
Control ctrl = viewer.getControl();
171         if (ctrl == null || ctrl.isDisposed()) {
172             return;
173         }
174
175         // Get the affected resource
176
final IResource resource = delta.getResource();
177     
178         // If any children have changed type, just do a full refresh of this
179
// parent,
180
// since a simple update on such children won't work,
181
// and trying to map the change to a remove and add is too dicey.
182
// The case is: folder A renamed to existing file B, answering yes to
183
// overwrite B.
184
IResourceDelta[] affectedChildren = delta
185                 .getAffectedChildren(IResourceDelta.CHANGED);
186         for (int i = 0; i < affectedChildren.length; i++) {
187             if ((affectedChildren[i].getFlags() & IResourceDelta.TYPE) != 0) {
188                 runnables.add(getRefreshRunnable(resource));
189                 return;
190             }
191         }
192
193         // Opening a project just affects icon, but we need to refresh when
194
// a project is closed because if child items have not yet been created
195
// in the tree we still need to update the item's children
196
int changeFlags = delta.getFlags();
197         if ((changeFlags & IResourceDelta.OPEN) != 0) {
198             if (resource.isAccessible()) {
199                 runnables.add(getUpdateRunnable(resource));
200             } else {
201                 runnables.add(getRefreshRunnable(resource));
202                 return;
203             }
204         }
205         // Check the flags for changes the Navigator cares about.
206
// See ResourceLabelProvider for the aspects it cares about.
207
// Notice we don't care about F_CONTENT or F_MARKERS currently.
208
if ((changeFlags & (IResourceDelta.SYNC
209                 | IResourceDelta.TYPE | IResourceDelta.DESCRIPTION)) != 0) {
210             runnables.add(getUpdateRunnable(resource));
211         }
212         // Replacing a resource may affect its label and its children
213
if ((changeFlags & IResourceDelta.REPLACED) != 0) {
214             runnables.add(getRefreshRunnable(resource));
215             return;
216         }
217
218         // Handle changed children .
219
for (int i = 0; i < affectedChildren.length; i++) {
220             processDelta(affectedChildren[i], runnables);
221         }
222
223         // @issue several problems here:
224
// - should process removals before additions, to avoid multiple equal
225
// elements in viewer
226
// - Kim: processing removals before additions was the indirect cause of
227
// 44081 and its varients
228
// - Nick: no delta should have an add and a remove on the same element,
229
// so processing adds first is probably OK
230
// - using setRedraw will cause extra flashiness
231
// - setRedraw is used even for simple changes
232
// - to avoid seeing a rename in two stages, should turn redraw on/off
233
// around combined removal and addition
234
// - Kim: done, and only in the case of a rename (both remove and add
235
// changes in one delta).
236

237         IResourceDelta[] addedChildren = delta
238                 .getAffectedChildren(IResourceDelta.ADDED);
239         IResourceDelta[] removedChildren = delta
240                 .getAffectedChildren(IResourceDelta.REMOVED);
241
242         if (addedChildren.length == 0 && removedChildren.length == 0) {
243             return;
244         }
245
246         final Object JavaDoc[] addedObjects;
247         final Object JavaDoc[] removedObjects;
248
249         // Process additions before removals as to not cause selection
250
// preservation prior to new objects being added
251
// Handle added children. Issue one update for all insertions.
252
int numMovedFrom = 0;
253         int numMovedTo = 0;
254         if (addedChildren.length > 0) {
255             addedObjects = new Object JavaDoc[addedChildren.length];
256             for (int i = 0; i < addedChildren.length; i++) {
257                 addedObjects[i] = addedChildren[i].getResource();
258                 if ((addedChildren[i].getFlags() & IResourceDelta.MOVED_FROM) != 0) {
259                     ++numMovedFrom;
260                 }
261             }
262         } else {
263             addedObjects = new Object JavaDoc[0];
264         }
265
266         // Handle removed children. Issue one update for all removals.
267
if (removedChildren.length > 0) {
268             removedObjects = new Object JavaDoc[removedChildren.length];
269             for (int i = 0; i < removedChildren.length; i++) {
270                 removedObjects[i] = removedChildren[i].getResource();
271                 if ((removedChildren[i].getFlags() & IResourceDelta.MOVED_TO) != 0) {
272                     ++numMovedTo;
273                 }
274             }
275         } else {
276             removedObjects = new Object JavaDoc[0];
277         }
278         // heuristic test for items moving within same folder (i.e. renames)
279
final boolean hasRename = numMovedFrom > 0 && numMovedTo > 0;
280         
281         Runnable JavaDoc addAndRemove = new Runnable JavaDoc(){
282             public void run() {
283                 if (viewer instanceof AbstractTreeViewer) {
284                     AbstractTreeViewer treeViewer = (AbstractTreeViewer) viewer;
285                     // Disable redraw until the operation is finished so we don't
286
// get a flash of both the new and old item (in the case of
287
// rename)
288
// Only do this if we're both adding and removing files (the
289
// rename case)
290
if (hasRename) {
291                         treeViewer.getControl().setRedraw(false);
292                     }
293                     try {
294                         if (addedObjects.length > 0) {
295                             treeViewer.add(resource, addedObjects);
296                         }
297                         if (removedObjects.length > 0) {
298                             treeViewer.remove(removedObjects);
299                         }
300                     }
301                     finally {
302                         if (hasRename) {
303                             treeViewer.getControl().setRedraw(true);
304                         }
305                     }
306                 } else {
307                     ((StructuredViewer) viewer).refresh(resource);
308                 }
309             }
310         };
311         runnables.add(addAndRemove);
312     }
313     /**
314      * Return a runnable for refreshing a resource.
315      * @param resource
316      * @return Runnable
317      */

318     private Runnable JavaDoc getRefreshRunnable(final IResource resource) {
319         return new Runnable JavaDoc(){
320             public void run() {
321                 ((StructuredViewer) viewer).refresh(resource);
322             }
323         };
324     }
325
326         /**
327          * Return a runnable for refreshing a resource.
328          * @param resource
329          * @return Runnable
330          */

331         private Runnable JavaDoc getUpdateRunnable(final IResource resource) {
332             return new Runnable JavaDoc(){
333                 public void run() {
334                     ((StructuredViewer) viewer).update(resource, null);
335                 }
336             };
337         }
338 }
339
Popular Tags