KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > progress > ProgressViewUpdater


1 /*******************************************************************************
2  * Copyright (c) 2003, 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.internal.progress;
12
13 import java.util.Collection JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.core.runtime.IStatus;
19 import org.eclipse.core.runtime.Status;
20 import org.eclipse.core.runtime.jobs.Job;
21 import org.eclipse.ui.IWorkbenchPreferenceConstants;
22 import org.eclipse.ui.PlatformUI;
23 import org.eclipse.ui.internal.util.PrefUtil;
24 import org.eclipse.ui.progress.WorkbenchJob;
25
26 /**
27  * The ProgressViewUpdater is the singleton that updates viewers.
28  */

29 class ProgressViewUpdater implements IJobProgressManagerListener {
30
31     private static ProgressViewUpdater singleton;
32
33     private IProgressUpdateCollector[] collectors;
34
35     Job updateJob;
36
37     UpdatesInfo currentInfo = new UpdatesInfo();
38
39     Object JavaDoc updateLock = new Object JavaDoc();
40
41     boolean debug;
42     
43    
44     /**
45      * The UpdatesInfo is a private class for keeping track of the updates
46      * required.
47      */

48     class UpdatesInfo {
49
50         Collection JavaDoc additions = new HashSet JavaDoc();
51
52         Collection JavaDoc deletions = new HashSet JavaDoc();
53
54         Collection JavaDoc refreshes = new HashSet JavaDoc();
55
56         boolean updateAll = false;
57
58         private UpdatesInfo() {
59             //Create a new instance of the info
60
}
61
62         /**
63          * Add an add update
64          *
65          * @param addition
66          */

67         void add(JobTreeElement addition) {
68             additions.add(addition);
69         }
70
71         /**
72          * Add a remove update
73          *
74          * @param removal
75          */

76         void remove(JobTreeElement removal) {
77             deletions.add(removal);
78         }
79
80         /**
81          * Add a refresh update
82          *
83          * @param refresh
84          */

85         void refresh(JobTreeElement refresh) {
86             refreshes.add(refresh);
87         }
88
89         /**
90          * Reset the caches after completion of an update.
91          */

92         void reset() {
93             additions.clear();
94             deletions.clear();
95             refreshes.clear();
96             updateAll = false;
97         }
98
99         void processForUpdate() {
100             HashSet JavaDoc staleAdditions = new HashSet JavaDoc();
101
102             Iterator JavaDoc additionsIterator = additions.iterator();
103             while (additionsIterator.hasNext()) {
104                 JobTreeElement treeElement = (JobTreeElement) additionsIterator
105                         .next();
106                 if (!treeElement.isActive()) {
107                     if (deletions.contains(treeElement)) {
108                         staleAdditions.add(treeElement);
109                     }
110                 }
111             }
112
113             additions.removeAll(staleAdditions);
114
115             HashSet JavaDoc obsoleteRefresh = new HashSet JavaDoc();
116             Iterator JavaDoc refreshIterator = refreshes.iterator();
117             while (refreshIterator.hasNext()) {
118                 JobTreeElement treeElement = (JobTreeElement) refreshIterator
119                         .next();
120                 if (deletions.contains(treeElement)
121                         || additions.contains(treeElement)) {
122                     obsoleteRefresh.add(treeElement);
123                 }
124                 
125                 //Also check for groups that are being added
126
Object JavaDoc parent = treeElement.getParent();
127                if(parent != null && (deletions.contains(parent)
128                        || additions.contains(parent))){
129                    obsoleteRefresh.add(treeElement);
130                }
131                
132                 if (!treeElement.isActive()) {
133                     //If it is done then delete it
134
obsoleteRefresh.add(treeElement);
135                     deletions.add(treeElement);
136                 }
137             }
138
139             refreshes.removeAll(obsoleteRefresh);
140
141         }
142     }
143
144     /**
145      * Return a new instance of the receiver.
146      *
147      * @return ProgressViewUpdater
148      */

149    static ProgressViewUpdater getSingleton() {
150         if (singleton == null) {
151             singleton = new ProgressViewUpdater();
152         }
153         return singleton;
154     }
155
156     /**
157      * Return whether or not there is a singleton for updates to avoid creating
158      * extra listeners.
159      *
160      * @return boolean <code>true</code> if there is already
161      * a singleton
162      */

163     static boolean hasSingleton() {
164         return singleton != null;
165     }
166
167     static void clearSingleton() {
168         if (singleton != null) {
169             ProgressManager.getInstance().removeListener(singleton);
170         }
171         singleton = null;
172     }
173
174     /**
175      * Create a new instance of the receiver.
176      */

177     private ProgressViewUpdater() {
178         createUpdateJob();
179         collectors = new IProgressUpdateCollector[0];
180         ProgressManager.getInstance().addListener(this);
181         debug =
182             PrefUtil.getAPIPreferenceStore().
183                 getBoolean(IWorkbenchPreferenceConstants.SHOW_SYSTEM_JOBS);
184     }
185
186     /**
187      * Add the new collector to the list of collectors.
188      *
189      * @param newCollector
190      */

191     void addCollector(IProgressUpdateCollector newCollector) {
192         IProgressUpdateCollector[] newCollectors = new IProgressUpdateCollector[collectors.length + 1];
193         System.arraycopy(collectors, 0, newCollectors, 0, collectors.length);
194         newCollectors[collectors.length] = newCollector;
195         collectors = newCollectors;
196     }
197
198     /**
199      * Remove the collector from the list of collectors.
200      *
201      * @param provider
202      */

203     void removeCollector(IProgressUpdateCollector provider) {
204         HashSet JavaDoc newCollectors = new HashSet JavaDoc();
205         for (int i = 0; i < collectors.length; i++) {
206             if (!collectors[i].equals(provider)) {
207                 newCollectors.add(collectors[i]);
208             }
209         }
210         IProgressUpdateCollector[] newArray = new IProgressUpdateCollector[newCollectors
211                 .size()];
212         newCollectors.toArray(newArray);
213         collectors = newArray;
214         //Remove ourselves if there is nothing to update
215
if (collectors.length == 0) {
216             clearSingleton();
217         }
218     }
219
220     /**
221      * Schedule an update.
222      */

223     void scheduleUpdate() {
224         if (PlatformUI.isWorkbenchRunning()) {
225             //Add in a 100ms delay so as to keep priority low
226
updateJob.schedule(100);
227         }
228     }
229
230     /**
231      * Create the update job that handles the updatesInfo.
232      */

233     private void createUpdateJob() {
234         updateJob = new WorkbenchJob(ProgressMessages.ProgressContentProvider_UpdateProgressJob) {
235             /*
236              * (non-Javadoc)
237              *
238              * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
239              */

240             public IStatus runInUIThread(IProgressMonitor monitor) {
241
242                 //Abort the job if there isn't anything
243
if (collectors.length == 0) {
244                     return Status.CANCEL_STATUS;
245                 }
246
247                 if (currentInfo.updateAll) {
248                     synchronized (updateLock) {
249                         currentInfo.reset();
250                     }
251                     for (int i = 0; i < collectors.length; i++) {
252                         collectors[i].refresh();
253                     }
254
255                 } else {
256                     //Lock while getting local copies of the caches.
257
Object JavaDoc[] updateItems;
258                     Object JavaDoc[] additionItems;
259                     Object JavaDoc[] deletionItems;
260                     synchronized (updateLock) {
261                         currentInfo.processForUpdate();
262
263                         updateItems = currentInfo.refreshes.toArray();
264                         additionItems = currentInfo.additions.toArray();
265                         deletionItems = currentInfo.deletions.toArray();
266
267                         currentInfo.reset();
268                     }
269
270                     for (int v = 0; v < collectors.length; v++) {
271                         IProgressUpdateCollector collector = collectors[v];
272
273                         if (updateItems.length > 0) {
274                             collector.refresh(updateItems);
275                         }
276                         if (additionItems.length > 0) {
277                             collector.add(additionItems);
278                         }
279                         if (deletionItems.length > 0) {
280                             collector.remove(deletionItems);
281                         }
282                     }
283                 }
284
285                 return Status.OK_STATUS;
286             }
287         };
288         updateJob.setSystem(true);
289         updateJob.setPriority(Job.DECORATE);
290         updateJob.setProperty(ProgressManagerUtil.INFRASTRUCTURE_PROPERTY, new Object JavaDoc());
291
292     }
293
294     /**
295      * Get the updates info that we are using in the receiver.
296      *
297      * @return Returns the currentInfo.
298      */

299     UpdatesInfo getCurrentInfo() {
300         return currentInfo;
301     }
302
303     /**
304      * Refresh the supplied JobInfo.
305      * @param info
306      */

307     public void refresh(JobInfo info) {
308
309         if (isUpdateJob(info.getJob())) {
310             return;
311         }
312
313         synchronized (updateLock) {
314             currentInfo.refresh(info);
315             GroupInfo group = info.getGroupInfo();
316             if (group != null) {
317                 currentInfo.refresh(group);
318             }
319         }
320         //Add in a 100ms delay so as to keep priority low
321
scheduleUpdate();
322
323     }
324
325     /* (non-Javadoc)
326      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshJobInfo(org.eclipse.ui.internal.progress.JobInfo)
327      */

328     public void refreshJobInfo(JobInfo info) {
329
330         if (isUpdateJob(info.getJob())) {
331             return;
332         }
333
334         synchronized (updateLock) {
335             currentInfo.refresh(info);
336         }
337         //Add in a 100ms delay so as to keep priority low
338
scheduleUpdate();
339
340     }
341
342     /* (non-Javadoc)
343      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshGroup(org.eclipse.ui.internal.progress.GroupInfo)
344      */

345     public void refreshGroup(GroupInfo info) {
346         synchronized (updateLock) {
347             currentInfo.refresh(info);
348         }
349         //Add in a 100ms delay so as to keep priority low
350
scheduleUpdate();
351
352     }
353
354     /* (non-Javadoc)
355      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#addGroup(org.eclipse.ui.internal.progress.GroupInfo)
356      */

357     public void addGroup(GroupInfo info) {
358
359         synchronized (updateLock) {
360             currentInfo.add(info);
361         }
362         scheduleUpdate();
363
364     }
365
366     /*
367      * (non-Javadoc)
368      *
369      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshAll()
370      */

371     public void refreshAll() {
372
373         synchronized (updateLock) {
374             currentInfo.updateAll = true;
375         }
376
377         //Add in a 100ms delay so as to keep priority low
378
scheduleUpdate();
379
380     }
381
382     /*
383      * (non-Javadoc)
384      *
385      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#add(org.eclipse.ui.internal.progress.JobInfo)
386      */

387     public void addJob(JobInfo info) {
388
389         if (isUpdateJob(info.getJob())) {
390             return;
391         }
392
393         synchronized (updateLock) {
394             GroupInfo group = info.getGroupInfo();
395
396             if (group == null) {
397                 currentInfo.add(info);
398             } else {
399                 currentInfo.refresh(group);
400             }
401         }
402         scheduleUpdate();
403
404     }
405
406     /*
407      * (non-Javadoc)
408      *
409      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#removeJob(org.eclipse.ui.internal.progress.JobInfo)
410      */

411     public void removeJob(JobInfo info) {
412
413         if (isUpdateJob(info.getJob())) {
414             return;
415         }
416
417         synchronized (updateLock) {
418             GroupInfo group = info.getGroupInfo();
419             if (group == null) {
420                 currentInfo.remove(info);
421             } else {
422                 group.removeJobInfo(info);
423                 currentInfo.refresh(group);
424             }
425         }
426         scheduleUpdate();
427     }
428
429     /* (non-Javadoc)
430      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#removeGroup(org.eclipse.ui.internal.progress.GroupInfo)
431      */

432     public void removeGroup(GroupInfo group) {
433         synchronized (updateLock) {
434             currentInfo.remove(group);
435         }
436         scheduleUpdate();
437
438     }
439
440     /*
441      * (non-Javadoc)
442      *
443      * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#showsDebug()
444      */

445     public boolean showsDebug() {
446         return debug;
447     }
448
449     /**
450      * Return whether or not this is the update job. This is used to determine
451      * if a final refresh is required.
452      *
453      * @param job
454      * @return boolean <code>true</true> if this is the
455      * update job
456      */

457     boolean isUpdateJob(Job job) {
458         return job.equals(updateJob);
459     }
460 }
461
Popular Tags