KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > resource > ResourceManager


1 /*******************************************************************************
2  * Copyright (c) 2004, 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.jface.resource;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.core.runtime.Assert;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.Status;
19 import org.eclipse.jface.util.Policy;
20 import org.eclipse.swt.SWTException;
21 import org.eclipse.swt.graphics.Color;
22 import org.eclipse.swt.graphics.Device;
23 import org.eclipse.swt.graphics.Font;
24 import org.eclipse.swt.graphics.Image;
25 import org.eclipse.swt.graphics.RGB;
26
27 /**
28  * This class manages SWT resources. It manages reference-counted instances of resources
29  * such as Fonts, Images, and Colors, and allows them to be accessed using descriptors.
30  * Everything allocated through the registry should also be disposed through the registry.
31  * Since the resources are shared and reference counted, they should never be disposed
32  * directly.
33  * <p>
34  * ResourceManager handles correct allocation and disposal of resources. It differs from
35  * the various JFace *Registry classes, which also map symbolic IDs onto resources. In
36  * general, you should use a *Registry class to map IDs onto descriptors, and use a
37  * ResourceManager to convert the descriptors into real Images/Fonts/etc.
38  * </p>
39  *
40  * @since 3.1
41  */

42 public abstract class ResourceManager {
43     
44     /**
45      * List of Runnables scheduled to run when the ResourceManager is disposed.
46      * null if empty.
47      */

48     private List JavaDoc disposeExecs = null;
49     
50     /**
51      * Returns the Device for which this ResourceManager will create resources
52      *
53      * @since 3.1
54      *
55      * @return the Device associated with this ResourceManager
56      */

57     public abstract Device getDevice();
58     
59     /**
60      * Returns the resource described by the given descriptor. If the resource already
61      * exists, the reference count is incremented and the exiting resource is returned.
62      * Otherwise, a new resource is allocated. Every call to this method should have
63      * a corresponding call to {@link #destroy(DeviceResourceDescriptor)}.
64      *
65      * <p>If the resource is intended to live for entire lifetime of the resource manager,
66      * a subsequent call to {@link #destroy(DeviceResourceDescriptor)} may be omitted and the
67      * resource will be cleaned up when the resource manager is disposed. This pattern
68      * is useful for short-lived {@link LocalResourceManager}s, but should never be used
69      * with the global resource manager since doing so effectively leaks the resource.</p>
70      *
71      * <p>The resources returned from this method are reference counted and may be shared
72      * internally with other resource managers. They should never be disposed outside of the
73      * ResourceManager framework, or it will cause exceptions in other code that shares
74      * them. For example, never call {@link org.eclipse.swt.graphics.Resource#dispose()}
75      * on anything returned from this method.</p>
76      *
77      * <p>Callers may safely downcast the result to the resource type associated with
78      * the descriptor. For example, when given an ImageDescriptor, the return
79      * value of this method will always be an Image.</p>
80      *
81      * @since 3.1
82      *
83      * @param descriptor descriptor for the resource to allocate
84      * @return the newly allocated resource (not null)
85      * @throws DeviceResourceException if unable to allocate the resource
86      */

87     public abstract Object JavaDoc create(DeviceResourceDescriptor descriptor);
88     
89     /**
90      * Deallocates a resource previously allocated by {@link #create(DeviceResourceDescriptor)}.
91      * Descriptors are compared by equality, not identity. If the same resource was
92      * created multiple times, this may decrement a reference count rather than
93      * disposing the actual resource.
94      *
95      * @since 3.1
96      *
97      * @param descriptor identifier for the resource
98      */

99     public abstract void destroy(DeviceResourceDescriptor descriptor);
100     
101     /**
102      * <p>Returns a previously-allocated resource or allocates a new one if none
103      * exists yet. The resource will remain allocated for at least the lifetime
104      * of this resource manager. If necessary, the resource will be deallocated
105      * automatically when the resource manager is disposed.</p>
106      *
107      * <p>The resources returned from this method are reference counted and may be shared
108      * internally with other resource managers. They should never be disposed outside of the
109      * ResourceManager framework, or it will cause exceptions in other code that shares
110      * them. For example, never call {@link org.eclipse.swt.graphics.Resource#dispose()}
111      * on anything returned from this method.</p>
112      *
113      * <p>
114      * Callers may safely downcast the result to the resource type associated with
115      * the descriptor. For example, when given an ImageDescriptor, the return
116      * value of this method may be downcast to Image.
117      * </p>
118      *
119      * <p>
120      * This method should only be used for resources that should remain
121      * allocated for the lifetime of the resource manager. To allocate shorter-lived
122      * resources, manage them with <code>create</code>, and <code>destroy</code>
123      * rather than this method.
124      * </p>
125      *
126      * <p>
127      * This method should never be called on the global resource manager,
128      * since all resources will remain allocated for the lifetime of the app and
129      * will be effectively leaked.
130      * </p>
131      *
132      * @param descriptor identifier for the requested resource
133      * @return the requested resource. Never null.
134      * @throws DeviceResourceException if the resource does not exist yet and cannot
135      * be created for any reason.
136      *
137      * @since 3.3
138      */

139     public final Object JavaDoc get(DeviceResourceDescriptor descriptor) {
140         Object JavaDoc result = find(descriptor);
141         
142         if (result == null) {
143             result = create(descriptor);
144         }
145         
146         return result;
147     }
148     
149     /**
150      * <p>Creates an image, given an image descriptor. Images allocated in this manner must
151      * be disposed by {@link #destroyImage(ImageDescriptor)}, and never by calling
152      * {@link Image#dispose()}.</p>
153      *
154      * <p>
155      * If the image is intended to remain allocated for the lifetime of the ResourceManager,
156      * the call to destroyImage may be omitted and the image will be cleaned up automatically
157      * when the ResourceManager is disposed. This should only be done with short-lived ResourceManagers,
158      * as doing so with the global manager effectively leaks the resource.
159      * </p>
160      *
161      * @since 3.1
162      *
163      * @param descriptor descriptor for the image to create
164      * @return the Image described by this descriptor (possibly shared by other equivalent
165      * ImageDescriptors)
166      * @throws DeviceResourceException if unable to allocate the Image
167      */

168     public final Image createImage(ImageDescriptor descriptor) {
169         // Assertion added to help diagnose client bugs. See bug #83711 and bug #90454.
170
Assert.isNotNull(descriptor);
171         
172         return (Image)create(descriptor);
173     }
174     
175     /**
176      * Creates an image, given an image descriptor. Images allocated in this manner must
177      * be disposed by {@link #destroyImage(ImageDescriptor)}, and never by calling
178      * {@link Image#dispose()}.
179      *
180      * @since 3.1
181      *
182      * @param descriptor descriptor for the image to create
183      * @return the Image described by this descriptor (possibly shared by other equivalent
184      * ImageDescriptors)
185      */

186     public final Image createImageWithDefault(ImageDescriptor descriptor) {
187         if (descriptor == null) {
188             return getDefaultImage();
189         }
190         
191         try {
192             return (Image) create(descriptor);
193         } catch (DeviceResourceException e) {
194             Policy.getLog().log(
195                     new Status(IStatus.WARNING, "org.eclipse.jface", 0, //$NON-NLS-1$
196
"The image could not be loaded: " + descriptor, //$NON-NLS-1$
197
e));
198             return getDefaultImage();
199         } catch (SWTException e) {
200             Policy.getLog().log(
201                     new Status(IStatus.WARNING, "org.eclipse.jface", 0, //$NON-NLS-1$
202
"The image could not be loaded: " + descriptor, //$NON-NLS-1$
203
e));
204             return getDefaultImage();
205         }
206     }
207     
208     /**
209      * Returns the default image that will be returned in the event that the intended
210      * image is missing.
211      *
212      * @since 3.1
213      *
214      * @return a default image that will be returned in the event that the intended
215      * image is missing.
216      */

217     protected abstract Image getDefaultImage();
218
219     /**
220      * Undoes everything that was done by {@link #createImage(ImageDescriptor)}.
221      *
222      * @since 3.1
223      *
224      * @param descriptor identifier for the image to dispose
225      */

226     public final void destroyImage(ImageDescriptor descriptor) {
227         destroy(descriptor);
228     }
229
230     /**
231      * Allocates a color, given a color descriptor. Any color allocated in this
232      * manner must be disposed by calling {@link #destroyColor(ColorDescriptor)},
233      * or by an eventual call to {@link #dispose()}. {@link Color#dispose()} must
234      * never been called directly on the returned color.
235      *
236      * @since 3.1
237      *
238      * @param descriptor descriptor for the color to create
239      * @return the Color described by the given ColorDescriptor (not null)
240      * @throws DeviceResourceException if unable to create the color
241      */

242     public final Color createColor(ColorDescriptor descriptor) {
243         return (Color)create(descriptor);
244     }
245
246     /**
247      * Allocates a color, given its RGB value. Any color allocated in this
248      * manner must be disposed by calling {@link #destroyColor(RGB)},
249      * or by an eventual call to {@link #dispose()}. {@link Color#dispose()} must
250      * never been called directly on the returned color.
251      *
252      * @since 3.1
253      *
254      * @param descriptor descriptor for the color to create
255      * @return the Color described by the given ColorDescriptor (not null)
256      * @throws DeviceResourceException if unable to create the color
257      */

258     public final Color createColor(RGB descriptor) {
259         return createColor(new RGBColorDescriptor(descriptor));
260     }
261     
262     /**
263      * Undoes everything that was done by a call to {@link #createColor(RGB)}.
264      *
265      * @since 3.1
266      *
267      * @param descriptor RGB value of the color to dispose
268      */

269     public final void destroyColor(RGB descriptor) {
270         destroyColor(new RGBColorDescriptor(descriptor));
271     }
272
273     /**
274      * Undoes everything that was done by a call to {@link #createColor(ColorDescriptor)}.
275      *
276      *
277      * @since 3.1
278      *
279      * @param descriptor identifier for the color to dispose
280      */

281     public final void destroyColor(ColorDescriptor descriptor) {
282         destroy(descriptor);
283     }
284     
285     /**
286      * Returns the Font described by the given FontDescriptor. Any Font
287      * allocated in this manner must be deallocated by calling disposeFont(...),
288      * or by an eventual call to {@link #dispose()}. The method {@link Font#dispose()}
289      * must never be called directly on the returned font.
290      *
291      * @since 3.1
292      *
293      * @param descriptor description of the font to create
294      * @return the Font described by the given descriptor
295      * @throws DeviceResourceException if unable to create the font
296      */

297     public final Font createFont(FontDescriptor descriptor) {
298         return (Font)create(descriptor);
299     }
300     
301     /**
302      * Undoes everything that was done by a previous call to {@link #createFont(FontDescriptor)}.
303      *
304      * @since 3.1
305      *
306      * @param descriptor description of the font to destroy
307      */

308     public final void destroyFont(FontDescriptor descriptor) {
309         destroy(descriptor);
310     }
311     
312     /**
313      * Disposes any remaining resources allocated by this manager.
314      */

315     public void dispose() {
316         if (disposeExecs == null) {
317             return;
318         }
319         
320         // If one of the runnables throws an exception, we need to propagate it.
321
// However, this should not prevent the remaining runnables from being
322
// notified. If any runnables throw an exception, we remember one of them
323
// here and throw it at the end of the method.
324
RuntimeException JavaDoc foundException = null;
325         
326         Runnable JavaDoc[] execs = (Runnable JavaDoc[]) disposeExecs.toArray(new Runnable JavaDoc[disposeExecs.size()]);
327         for (int i = 0; i < execs.length; i++) {
328             Runnable JavaDoc exec = execs[i];
329             
330             try {
331                 exec.run();
332             } catch (RuntimeException JavaDoc e) {
333                 // Ensure that we propagate an exception, but don't stop notifying
334
// the remaining runnables.
335
foundException = e;
336             }
337         }
338         
339         if (foundException != null) {
340             // If any runnables threw an exception, propagate one of them.
341
throw foundException;
342         }
343     }
344     
345     /**
346      * Returns a previously allocated resource associated with the given descriptor, or
347      * null if none exists yet.
348      *
349      * @since 3.1
350      *
351      * @param descriptor descriptor to find
352      * @return a previously allocated resource for the given descriptor or null if none.
353      */

354     public abstract Object JavaDoc find(DeviceResourceDescriptor descriptor);
355     
356     /**
357      * Causes the <code>run()</code> method of the runnable to
358      * be invoked just before the receiver is disposed. The runnable
359      * can be subsequently canceled by a call to <code>cancelDisposeExec</code>.
360      *
361      * @param r runnable to execute.
362      */

363     public void disposeExec(Runnable JavaDoc r) {
364         Assert.isNotNull(r);
365         
366         if (disposeExecs == null) {
367             disposeExecs = new ArrayList JavaDoc();
368         }
369         
370         disposeExecs.add(r);
371     }
372     
373     /**
374      * Cancels a runnable that was previously scheduled with <code>disposeExec</code>.
375      * Has no effect if the given runnable was not previously registered with
376      * disposeExec.
377      *
378      * @param r runnable to cancel
379      */

380     public void cancelDisposeExec(Runnable JavaDoc r) {
381         Assert.isNotNull(r);
382         
383         if (disposeExecs == null) {
384             return;
385         }
386         
387         disposeExecs.remove(r);
388         
389         if (disposeExecs.isEmpty()) {
390             disposeExecs = null;
391         }
392     }
393 }
394
Popular Tags