KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > views > tasklist > TaskListContentProvider


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
12 package org.eclipse.ui.views.tasklist;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Set JavaDoc;
20
21 import org.eclipse.core.resources.IMarker;
22 import org.eclipse.core.resources.IMarkerDelta;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.resources.IResourceChangeEvent;
25 import org.eclipse.core.resources.IResourceChangeListener;
26 import org.eclipse.core.resources.IResourceDelta;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.jface.viewers.IStructuredContentProvider;
29 import org.eclipse.jface.viewers.IStructuredSelection;
30 import org.eclipse.jface.viewers.TableViewer;
31 import org.eclipse.jface.viewers.Viewer;
32 import org.eclipse.osgi.util.NLS;
33 import org.eclipse.swt.widgets.Control;
34 import org.eclipse.ui.internal.views.tasklist.TaskListMessages;
35
36 /**
37  * Task list content provider returns elements that should be
38  * in the task list depending on the selection mode.
39  * It goes directly to the marker manager and retreives
40  * tasks and problems.
41  */

42 class TaskListContentProvider implements IStructuredContentProvider,
43         IResourceChangeListener {
44
45     private static final int TASKS = 0;
46
47     private static final int ERRORS = 1;
48
49     private static final int WARNINGS = 2;
50
51     private static final int INFOS = 3;
52
53     private TaskList taskList;
54
55     private TableViewer viewer;
56
57     private IResource input;
58
59     /* cached counts of tasks, errors, warnings and infos for the visible
60      * markers, maintained incrementally */

61     private int[] visibleMarkerCounts = null;
62
63     /* cached count of all markers in workspace matching supported root types
64      * (tasks & problems), maintained incrementally */

65     private int totalMarkerCount = -1;
66
67     /**
68      * The constructor.
69      */

70     public TaskListContentProvider(TaskList taskList) {
71         this.taskList = taskList;
72         this.viewer = taskList.getTableViewer();
73     }
74
75     private boolean getFilterOnMarkerLimit() {
76         return taskList.getFilter().getFilterOnMarkerLimit();
77     }
78
79     private int getMarkerLimit() {
80         return taskList.getFilter().getMarkerLimit();
81     }
82
83     private boolean isMarkerLimitExceeded() {
84         return taskList.isMarkerLimitExceeded();
85     }
86
87     private void setMarkerLimitExceeded(boolean markerLimitExceeded) {
88         taskList.setMarkerLimitExceeded(markerLimitExceeded);
89     }
90
91     /**
92      * Returns a one-line string containing a summary of the number
93      * of visible tasks and problems.
94      */

95     public String JavaDoc getStatusSummaryVisible() {
96         if (visibleMarkerCounts == null) {
97             return ""; //$NON-NLS-1$
98
}
99
100         return NLS.bind(TaskListMessages.TaskList_statusSummaryVisible,new Integer JavaDoc(sum(visibleMarkerCounts)),
101         getStatusSummaryBreakdown(visibleMarkerCounts));
102     }
103
104     /**
105      * Returns a one-line string containing a summary of the number
106      * of selected tasks and problems.
107      *
108      * @param selection the current selection
109      */

110     public String JavaDoc getStatusSummarySelected(IStructuredSelection selection) {
111         int[] selectedMarkerCounts = getMarkerCounts(selection.toList());
112         return NLS.bind(TaskListMessages.TaskList_statusSummarySelected, new Integer JavaDoc(sum(selectedMarkerCounts)),
113         getStatusSummaryBreakdown(selectedMarkerCounts) );
114     }
115
116     /**
117      * Returns a one-line string containing a summary of the number of
118      * given tasks, errors, warnings, and infos.
119      */

120     private String JavaDoc getStatusSummaryBreakdown(int[] counts) {
121         return NLS.bind(
122                 TaskListMessages.TaskList_statusSummaryBreakdown,
123                 new Object JavaDoc []{
124                         new Integer JavaDoc(counts[TASKS]),
125                         new Integer JavaDoc(counts[ERRORS]),
126                         new Integer JavaDoc(counts[WARNINGS]),
127                         new Integer JavaDoc(counts[INFOS])});
128     }
129
130     /**
131      * Returns a one-line string containing a summary of the number items
132      * being shown by the filter, for display in the title bar.
133      */

134     public String JavaDoc getTitleSummary() {
135         if (visibleMarkerCounts == null) {
136             return ""; //$NON-NLS-1$
137
}
138
139         int visibleMarkerCount = sum(visibleMarkerCounts);
140         TasksFilter filter = taskList.getFilter();
141
142         if (filter.isShowingAll()) {
143             return NLS.bind(TaskListMessages.TaskList_titleSummaryUnfiltered, new Integer JavaDoc(visibleMarkerCount));
144         } else {
145             return NLS.bind(TaskListMessages.TaskList_titleSummaryFiltered, new Integer JavaDoc(visibleMarkerCount),
146             new Integer JavaDoc(getTotalMarkerCount()));
147         }
148     }
149
150     /**
151      * Returns the sum of the given counts.
152      */

153     private int sum(int[] counts) {
154         int sum = 0;
155
156         for (int i = 0, l = counts.length; i < l; ++i) {
157             sum += counts[i];
158         }
159
160         return sum;
161     }
162
163     /**
164      * Returns the count of all markers in the workspace which can be shown in
165      * the task list. This is computed once, then maintained incrementally by
166      * the delta processing.
167      */

168     private int getTotalMarkerCount() {
169         if (totalMarkerCount == -1) {
170             totalMarkerCount = 0;
171
172             try {
173                 IResource root = taskList.getWorkspace().getRoot();
174                 IMarker[] markers = root.findMarkers(null, true,
175                         IResource.DEPTH_INFINITE);
176
177                 for (int i = 0; i < markers.length; ++i) {
178                     if (isRootType(markers[i])) {
179                         ++totalMarkerCount;
180                     }
181                 }
182             } catch (CoreException e) {
183                 // shouldn't happen
184
}
185         }
186
187         return totalMarkerCount;
188     }
189
190     /**
191      * Returns whether the given marker is a subtype of one of the root types.
192      */

193     private boolean isRootType(IMarker marker) {
194         String JavaDoc[] rootTypes = TasksFilter.ROOT_TYPES;
195
196         for (int i = 0, l = rootTypes.length; i < l; ++i) {
197             if (MarkerUtil.isMarkerType(marker, rootTypes[i])) {
198                 return true;
199             }
200         }
201
202         return false;
203     }
204
205     /**
206      * Returns the markers to show in the task list.
207      */

208     private IMarker[] getMarkers() throws CoreException {
209         IResource[] resources = taskList.getResources();
210         int l = resources.length;
211         IResource resource;
212         boolean bExists = false;
213
214         for (int i = 0; i < l; i++) {
215             resource = resources[i];
216
217             if (resource != null && resource.exists()) {
218                 bExists = true;
219                 break;
220             }
221         }
222
223         if (!bExists) {
224             return new IMarker[0];
225         }
226
227         if (taskList.showOwnerProject()) {
228             IResource[] projectResources = new IResource[l];
229             IResource project;
230
231             for (int i = 0; i < l; i++) {
232                 resource = resources[i];
233
234                 if (resource != null) {
235                     project = resource.getProject();
236
237                     if (project != null) {
238                         projectResources[i] = project;
239                     } else {
240                         projectResources[i] = resource;
241                     }
242                 }
243             }
244
245             resources = projectResources;
246         }
247
248         int depth = taskList.getResourceDepth();
249         TasksFilter filter = taskList.getFilter();
250         Set JavaDoc set = new HashSet JavaDoc();
251
252         for (int i = 0; i < l; i++) {
253             resource = resources[i];
254
255             if (resource != null) {
256                 IMarker[] markers = resource.findMarkers(null, true, depth);
257
258                 for (int j = 0; j < markers.length; ++j) {
259                     IMarker marker = markers[j];
260
261                     if (filter.select(marker)) {
262                         set.add(marker);
263                     }
264                 }
265             }
266         }
267
268         IMarker[] result = new IMarker[set.size()];
269         set.toArray(result);
270         return result;
271     }
272
273     /**
274      * Returns the number of tasks, errors, warnings, infos
275      * in the given markers.
276      */

277     private int[] getMarkerCounts(List JavaDoc markers) {
278         int[] markerCounts = new int[4];
279         Iterator JavaDoc iterator = markers.iterator();
280
281         while (iterator.hasNext()) {
282             IMarker marker = (IMarker) iterator.next();
283
284             if (MarkerUtil.isMarkerType(marker, IMarker.PROBLEM)) {
285                 switch (MarkerUtil.getSeverity(marker)) {
286                 case IMarker.SEVERITY_ERROR:
287                     ++markerCounts[ERRORS];
288                     break;
289                 case IMarker.SEVERITY_WARNING:
290                     ++markerCounts[WARNINGS];
291                     break;
292                 case IMarker.SEVERITY_INFO:
293                     ++markerCounts[INFOS];
294                     break;
295                 }
296             } else if (MarkerUtil.isMarkerType(marker, IMarker.TASK)) {
297                 ++markerCounts[TASKS];
298             }
299         }
300
301         return markerCounts;
302     }
303
304     /**
305      * Updates the marker counts for the given delta.
306      * Assumptions:
307      * - the delta is either an addition or a removal
308      * - problem severities don't change
309      */

310     private void updateMarkerCounts(IMarkerDelta markerDelta, int difference) {
311         if (visibleMarkerCounts == null) {
312             return;
313         }
314
315         if (markerDelta.isSubtypeOf(IMarker.PROBLEM)) {
316             int severity = markerDelta.getAttribute(IMarker.SEVERITY,
317                     IMarker.SEVERITY_WARNING);
318
319             switch (severity) {
320             case IMarker.SEVERITY_ERROR:
321                 visibleMarkerCounts[ERRORS] += difference;
322                 break;
323             case IMarker.SEVERITY_WARNING:
324                 visibleMarkerCounts[WARNINGS] += difference;
325                 break;
326             case IMarker.SEVERITY_INFO:
327                 visibleMarkerCounts[INFOS] += difference;
328                 break;
329             }
330         } else if (markerDelta.isSubtypeOf(IMarker.TASK)) {
331             visibleMarkerCounts[TASKS] += difference;
332         }
333     }
334
335     /**
336      * Updates the viewer given the lists of added, removed, and changes
337      * markers. This is called inside an syncExec.
338      */

339     private void updateViewer(List JavaDoc additions, List JavaDoc removals, List JavaDoc changes) {
340
341         // The widget may have been destroyed by the time this is run.
342
// Check for this and do nothing if so.
343
Control ctrl = viewer.getControl();
344
345         if (ctrl == null || ctrl.isDisposed()) {
346             return;
347         }
348
349         //update the viewer based on the marker changes.
350
//process removals before additions, to avoid multiple equal elements in
351
//the viewer
352
if (removals.size() > 0) {
353
354             // Cancel any open cell editor. We assume that the one being edited
355
// is the one being removed.
356
viewer.cancelEditing();
357             viewer.remove(removals.toArray());
358         }
359
360         if (additions.size() > 0) {
361             viewer.add(additions.toArray());
362         }
363
364         if (changes.size() > 0) {
365             viewer.update(changes.toArray(), null);
366         }
367     }
368
369     /**
370      * The visual part that is using this content provider is about
371      * to be disposed. Deallocate all allocated SWT resources.
372      */

373     public void dispose() {
374         if (input != null) {
375             input.getWorkspace().removeResourceChangeListener(this);
376             input = null;
377         }
378     }
379
380     public void inputChanged(Viewer viewer, Object JavaDoc oldInput, Object JavaDoc newInput) {
381         if (this.input != null) {
382             this.input.getWorkspace().removeResourceChangeListener(this);
383         }
384
385         this.input = (IResource) newInput;
386
387         if (this.input != null) {
388             this.input.getWorkspace().addResourceChangeListener(this,
389                     IResourceChangeEvent.POST_CHANGE);
390         }
391
392         this.viewer = (TableViewer) viewer;
393     }
394
395     /**
396      * Returns all the markers that should be shown for
397      * the current settings.
398      */

399     public Object JavaDoc[] getElements(Object JavaDoc parent) {
400         try {
401             IMarker[] markers = getMarkers();
402             this.visibleMarkerCounts = getMarkerCounts(Arrays.asList(markers));
403
404             if (getFilterOnMarkerLimit() && markers.length > getMarkerLimit()) {
405                 if (!isMarkerLimitExceeded()) {
406                     setMarkerLimitExceeded(true);
407
408                     viewer.getControl().getDisplay().syncExec(new Runnable JavaDoc() {
409                         public void run() {
410                             viewer.refresh();
411                         }
412                     });
413                 }
414
415                 return new IMarker[0];
416             } else {
417                 if (isMarkerLimitExceeded()) {
418                     setMarkerLimitExceeded(false);
419
420                     viewer.getControl().getDisplay().syncExec(new Runnable JavaDoc() {
421                         public void run() {
422                             viewer.refresh();
423                         }
424                     });
425                 }
426
427                 return markers;
428             }
429         } catch (CoreException e) {
430             return new IMarker[0];
431         }
432     }
433
434     /**
435      * The workbench has changed. Process the delta and issue updates to the
436      * viewer, inside the UI thread.
437      *
438      * @see IResourceChangeListener#resourceChanged
439      */

440     public void resourceChanged(final IResourceChangeEvent event) {
441         /*
442          * gather all marker changes from the delta. be sure to do this in the
443          * calling thread, as the delta is destroyed when this method returns
444          */

445         IMarkerDelta[] markerDeltas = event.findMarkerDeltas(null, true);
446
447         if (markerDeltas == null) {
448             return;
449         }
450
451         int oldTotal = totalMarkerCount;
452         final List JavaDoc additions = new ArrayList JavaDoc();
453         final List JavaDoc removals = new ArrayList JavaDoc();
454         final List JavaDoc changes = new ArrayList JavaDoc();
455
456         for (int i = 0; i < markerDeltas.length; i++) {
457             IMarkerDelta markerDelta = markerDeltas[i];
458
459             if (markerDelta == null) {
460                 continue;
461             }
462
463             int iKind = markerDelta.getKind();
464
465             for (int j = 0; j < TasksFilter.ROOT_TYPES.length; j++) {
466                 if (markerDelta.isSubtypeOf(TasksFilter.ROOT_TYPES[j])) {
467
468                     /*
469                      * Updates the total count of markers given the applicable
470                      * marker deltas.
471                      */

472                     if (totalMarkerCount != -1) {
473                         switch (iKind) {
474                         case IResourceDelta.ADDED:
475                             totalMarkerCount++;
476                             break;
477                         case IResourceDelta.REMOVED:
478                             totalMarkerCount--;
479                             break;
480                         }
481                     }
482
483                     /*
484                      * Partition the marker deltas into one of the three given
485                      * lists depending on
486                      * the type of delta (add, remove, or change).
487                      * The resulting lists contain the corresponding markers,
488                      * not the deltas.
489                      * Deltas which are not under the current focus resource are
490                      * discarded.
491                      * This also updates the marker counts.
492                      */

493
494                     IResource resource = markerDelta.getResource();
495
496                     if (resource == null) {
497                         continue;
498                     }
499
500                     boolean affectedBy = taskList.checkResource(resource)
501                             && taskList.getFilter().select(markerDelta);
502
503                     if (affectedBy) {
504                         IMarker marker = markerDelta.getMarker();
505
506                         switch (iKind) {
507                         case IResourceDelta.ADDED:
508                             additions.add(marker);
509                             updateMarkerCounts(markerDelta, +1);
510                             break;
511                         case IResourceDelta.REMOVED:
512                             removals.add(marker);
513                             updateMarkerCounts(markerDelta, -1);
514                             break;
515                         case IResourceDelta.CHANGED:
516                             changes.add(marker);
517                             /*
518                              * Assume attribute changes don't affect marker
519                              * counts. This is only true if problem severities
520                              * can't change.
521                              */

522                             break;
523                         }
524                     }
525
526                     break;
527                 }
528             }
529         }
530
531         if (oldTotal == totalMarkerCount
532                 && additions.size() + removals.size() + changes.size() == 0) {
533             // no changes to markers that we care about
534
return;
535         }
536
537         /*
538          * do the required viewer updates in the UI thread need to use syncExec;
539          * see 1G95PU8: ITPUI:WIN2000 - Changing task description flashes old
540          * description
541          */

542         viewer.getControl().getDisplay().syncExec(new Runnable JavaDoc() {
543             public void run() {
544                 if (getFilterOnMarkerLimit()
545                         && sum(visibleMarkerCounts) > getMarkerLimit()) {
546                     if (!isMarkerLimitExceeded()) {
547                         setMarkerLimitExceeded(true);
548                         viewer.refresh();
549                     }
550                 } else if (taskList.isMarkerLimitExceeded()) {
551                     setMarkerLimitExceeded(false);
552                     viewer.refresh();
553                 } else {
554                     updateViewer(additions, removals, changes);
555                 }
556
557                 /* Update the task list's status message.
558                  * XXX: Quick and dirty solution here.
559                  * Would be better to have a separate model for the tasks and
560                  * have both the content provider and the task list register for
561                  * updates. XXX: Do this inside the syncExec, since we're
562                  * talking to status line widget.
563                  */

564                 taskList.markersChanged();
565             }
566         });
567     }
568 }
569
Popular Tags