KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > views > RemoteTreeContentManager


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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.debug.internal.ui.views;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.core.runtime.IAdaptable;
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.debug.internal.ui.DebugUIPlugin;
22 import org.eclipse.jface.viewers.ITreeContentProvider;
23 import org.eclipse.ui.IWorkbenchPartSite;
24 import org.eclipse.ui.internal.progress.PendingUpdateAdapter;
25 import org.eclipse.ui.model.IWorkbenchAdapter;
26 import org.eclipse.ui.progress.DeferredTreeContentManager;
27 import org.eclipse.ui.progress.IDeferredWorkbenchAdapter;
28 import org.eclipse.ui.progress.IElementCollector;
29 import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
30 import org.eclipse.ui.progress.WorkbenchJob;
31 import org.osgi.framework.Bundle;
32 /**
33  * A remote content manager that merges content into a tree rather then replacing
34  * its children with a "pending" node, and then the real children when they are available.
35  * This avoids collapsing the viewer when a refresh is performed. This implementation is
36  * currently tied to the <code>RemoteTreeViewer</code>.
37  *
38  * @since 3.1
39  */

40 public class RemoteTreeContentManager extends DeferredTreeContentManager {
41
42     private RemoteTreeViewer fViewer;
43     private IWorkbenchSiteProgressService progressService;
44     
45     /**
46      * Job to fetch children
47      */

48     private Job fFetchJob = new FetchJob();
49     
50     /**
51      * Queue of parents to fetch children for, and
52      * associated element collectors and deferred adapters.
53      */

54     private List JavaDoc fElementQueue = new ArrayList JavaDoc();
55     private List JavaDoc fCollectors = new ArrayList JavaDoc();
56     private List JavaDoc fAdapaters = new ArrayList JavaDoc();
57     
58     /**
59      * Fetching children is done in a single background job.
60      * This makes fetching single threaded/serial per view.
61      */

62     class FetchJob extends Job {
63         
64         public FetchJob() {
65             super(DebugUIViewsMessages.RemoteTreeContentManager_0);
66             setSystem(true);
67         }
68
69         /* (non-Javadoc)
70          * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
71          */

72         protected IStatus run(IProgressMonitor monitor) {
73             while (!fElementQueue.isEmpty() && !monitor.isCanceled()) {
74                 Object JavaDoc element = null;
75                 IElementCollector collector = null;
76                 IDeferredWorkbenchAdapter adapter = null;
77                 synchronized (fElementQueue) {
78                     // could have been cancelled after entering the while loop
79
if (fElementQueue.isEmpty()) {
80                         return Status.CANCEL_STATUS;
81                     }
82                     element = fElementQueue.remove(0);
83                     collector = (IElementCollector) fCollectors.remove(0);
84                     adapter = (IDeferredWorkbenchAdapter) fAdapaters.remove(0);
85                 }
86                 adapter.fetchDeferredChildren(element, collector, monitor);
87             }
88             if (monitor.isCanceled()) {
89                 return Status.CANCEL_STATUS;
90             }
91             return Status.OK_STATUS;
92         }
93         
94     }
95     
96     /**
97      * Element collector
98      */

99     public class Collector implements IElementCollector {
100         // number of children added to the tree
101
int offset = 0;
102         Object JavaDoc fParent;
103         
104         public Collector(Object JavaDoc parent) {
105             fParent = parent;
106         }
107         /*
108          * (non-Javadoc)
109          * @see org.eclipse.jface.progress.IElementCollector#add(java.lang.Object, org.eclipse.core.runtime.IProgressMonitor)
110          */

111         public void add(Object JavaDoc element, IProgressMonitor monitor) {
112             add(new Object JavaDoc[] { element }, monitor);
113         }
114
115         /*
116          * (non-Javadoc)
117          * @see org.eclipse.jface.progress.IElementCollector#add(java.lang.Object[], org.eclipse.core.runtime.IProgressMonitor)
118          */

119         public void add(Object JavaDoc[] elements, IProgressMonitor monitor) {
120             Object JavaDoc[] filtered = fViewer.filter(elements);
121             if (filtered.length > 0) {
122                 replaceChildren(fParent, filtered, offset, monitor);
123                 offset = offset + filtered.length;
124             }
125         }
126
127         /*
128          * (non-Javadoc)
129          *
130          * @see org.eclipse.jface.progress.IElementCollector#done()
131          */

132         public void done() {
133             prune(fParent, offset);
134         }
135     }
136     
137     /**
138      * Contructs a new content manager.
139      *
140      * @param provider content provider
141      * @param viewer viewer
142      * @param site part site
143      */

144     public RemoteTreeContentManager(ITreeContentProvider provider, RemoteTreeViewer viewer, IWorkbenchPartSite site) {
145         super(provider, viewer, site);
146         fViewer = viewer;
147         Object JavaDoc siteService = site.getAdapter(IWorkbenchSiteProgressService.class);
148         if (siteService != null) {
149             progressService = (IWorkbenchSiteProgressService) siteService;
150         }
151     }
152     
153     /**
154      * Create the element collector for the receiver.
155      *@param parent
156      * The parent object being filled in,
157      * @param placeholder
158      * The adapter that will be used to indicate that results are
159      * pending, possibly <code>null</code>
160      * @return IElementCollector
161      */

162     protected IElementCollector createElementCollector(Object JavaDoc parent, PendingUpdateAdapter placeholder) {
163         return new Collector(parent);
164     }
165     
166     /**
167      * Returns the child elements of the given element, or in the case of a
168      * deferred element, returns a placeholder. If a deferred element is used, a
169      * job is created to fetch the children in the background.
170      *
171      * @param parent
172      * The parent object.
173      * @return Object[] or <code>null</code> if parent is not an instance of
174      * IDeferredWorkbenchAdapter.
175      */

176     public Object JavaDoc[] getChildren(final Object JavaDoc parent) {
177         IDeferredWorkbenchAdapter element = getAdapter(parent);
178         if (element == null)
179             return null;
180         Object JavaDoc[] currentChildren = fViewer.getCurrentChildren(parent);
181         PendingUpdateAdapter placeholder = null;
182         if (currentChildren == null || currentChildren.length == 0) {
183             placeholder = new PendingUpdateAdapter();
184         }
185         startFetchingDeferredChildren(parent, element, placeholder);
186         if (placeholder == null) {
187             return currentChildren;
188         }
189         return new Object JavaDoc[] { placeholder };
190     }
191     
192     /**
193      * Create a UIJob to replace the children of the parent in the tree viewer.
194      *
195      * @param parent the parent for which children are to be replaced
196      * @param children the replacement children
197      * @param offset the offset at which to start replacing children
198      * @param monitor progress monitor
199      */

200     protected void replaceChildren(final Object JavaDoc parent, final Object JavaDoc[] children, final int offset, IProgressMonitor monitor) {
201         if (monitor.isCanceled()) {
202             return;
203         }
204         WorkbenchJob updateJob = new WorkbenchJob(DebugUIViewsMessages.IncrementalDeferredTreeContentManager_0) { //$NON-NLS-1$
205
/*
206              * (non-Javadoc)
207              *
208              * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
209              */

210             public IStatus runInUIThread(IProgressMonitor updateMonitor) {
211                 //Cancel the job if the tree viewer got closed
212
if (fViewer.getControl().isDisposed())
213                     return Status.CANCEL_STATUS;
214                 fViewer.replace(parent, children, offset);
215                 return Status.OK_STATUS;
216             }
217         };
218         updateJob.setSystem(true);
219         updateJob.setPriority(Job.INTERACTIVE);
220         updateJob.schedule();
221     }
222     
223     /**
224      * Create a UIJob to prune the children of the parent in the tree viewer, starting
225      * at the given offset.
226      *
227      * @param parent the parent for which children should be pruned
228      * @param offset the offset at which children should be pruned. All children at and after
229      * this index will be removed from the tree.
230      * @param monitor
231      */

232     protected void prune(final Object JavaDoc parent, final int offset) {
233         WorkbenchJob updateJob = new WorkbenchJob(DebugUIViewsMessages.IncrementalDeferredTreeContentManager_1) { //$NON-NLS-1$
234
/*
235              * (non-Javadoc)
236              *
237              * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
238              */

239             public IStatus runInUIThread(IProgressMonitor updateMonitor) {
240                 //Cancel the job if the tree viewer got closed
241
if (fViewer.getControl().isDisposed())
242                     return Status.CANCEL_STATUS;
243                 fViewer.prune(parent, offset);
244                 return Status.OK_STATUS;
245             }
246         };
247         updateJob.setSystem(true);
248         updateJob.setPriority(Job.INTERACTIVE);
249         updateJob.schedule();
250     }
251     
252     /* (non-Javadoc)
253      * @see org.eclipse.ui.progress.DeferredTreeContentManager#runClearPlaceholderJob(org.eclipse.ui.internal.progress.PendingUpdateAdapter)
254      */

255     protected void runClearPlaceholderJob(PendingUpdateAdapter placeholder) {
256         // the placeholder is not used when there were already children in the tree (null)
257
if (placeholder != null) {
258             super.runClearPlaceholderJob(placeholder);
259         }
260     }
261
262     /* (non-Javadoc)
263      * @see org.eclipse.ui.progress.DeferredTreeContentManager#getFetchJobName(java.lang.Object, org.eclipse.ui.progress.IDeferredWorkbenchAdapter)
264      */

265     protected String JavaDoc getFetchJobName(Object JavaDoc parent, IDeferredWorkbenchAdapter adapter) {
266         return DebugUIViewsMessages.RemoteTreeContentManager_0; //$NON-NLS-1$
267
}
268     
269     
270     /**
271      * Returns the IDeferredWorkbenchAdapter for the element, or <code>null</code>.
272      * If a client has contributed an IWorkbenchAdapter for the element, it
273      * should be used in place of the debug platform's IDeferredWorkbenchAdapter,
274      * in which case, <code>null</code> is returned.
275      *
276      * @param element
277      * @return IDeferredWorkbenchAdapter or <code>null</code>
278      */

279     protected IDeferredWorkbenchAdapter getAdapter(Object JavaDoc element) {
280         if (element instanceof IDeferredWorkbenchAdapter)
281             return (IDeferredWorkbenchAdapter) element;
282         if (!(element instanceof IAdaptable))
283             return null;
284         IAdaptable adaptable = (IAdaptable) element;
285         IDeferredWorkbenchAdapter deferred = (IDeferredWorkbenchAdapter) adaptable.getAdapter(IDeferredWorkbenchAdapter.class);
286         if (deferred == null)
287             return null;
288         
289         DebugUIPlugin plugin = DebugUIPlugin.getDefault();
290         Bundle bundle = plugin.getBundle(deferred.getClass());
291         Bundle debugBundle = plugin.getBundle();
292         if (!debugBundle.equals(bundle)) {
293             // if client contributed, use it
294
return deferred;
295         }
296         // if the client provided an IWorkbenchAdapter, use it
297
IWorkbenchAdapter nonDeferred = (IWorkbenchAdapter) adaptable.getAdapter(IWorkbenchAdapter.class);
298         if (nonDeferred != null) {
299             bundle = plugin.getBundle(nonDeferred.getClass());
300             if (!debugBundle.equals(bundle)) {
301                 // by returning null, we'll revert to using the the object's workbench adapter
302
// by pretending it has no deffered adapter
303
return null;
304             }
305         }
306         return deferred;
307     }
308     
309     protected void startFetchingDeferredChildren(final Object JavaDoc parent, final IDeferredWorkbenchAdapter adapter, PendingUpdateAdapter placeholder) {
310         final IElementCollector collector = createElementCollector(parent, placeholder);
311         synchronized (fElementQueue) {
312             if (!fElementQueue.contains(parent)) {
313                 fElementQueue.add(parent);
314                 fCollectors.add(collector);
315                 fAdapaters.add(adapter);
316             }
317         }
318         if (progressService == null)
319             fFetchJob.schedule();
320         else
321             progressService.schedule(fFetchJob);
322     }
323     
324     /**
325      * Cancels any content this provider is currently fetching.
326      */

327     public void cancel() {
328         synchronized (fElementQueue) {
329             fFetchJob.cancel();
330             fElementQueue.clear();
331             fAdapaters.clear();
332             fCollectors.clear();
333         }
334     }
335 }
336
Popular Tags