Eclipse from the bottom up

The view of the Eclipse world from the bottom of the stack

Monday, May 01, 2006

Image Management

Just to follow up on what Tod mentioned in his blog about image management, the ResourceManager and ImageRegistry classes are not just about maqnaging the lifecycle of an image, they're also about how images can be shared. I thought it would be worthwhile to give a brief description of each of these classes.

ResourceManager: A resource manager can be used to keep track of a set of created Images. The client of this class is still responsible for creating and disposing of images but creation and disposal is done by calling the createImage(ImageDescriptor) and destryImage(ImageDescriptor) methods on ResourceManager. The obvious question is why would you want to use a resource manager if you still need to dispose of the image at some point. The reason is that the resource manager will ensure that, for a particular descriptor, the image is only created once, thus saving precious OS resources. The manager uses reference counting to ensure that the image is only disposed when it has been destroyed the same number of times it has been created.

So the advantage of using a resource manager is that you can reuse images but the disadvantage is that you still need to dispose of the images when you are done with them. However, disposal can be simplified somewhat by using a LocalResourceManager. Let's say I have a set of images that need to be available while a particular viewer is opened but can be disposed when the viewer is closed. I can create a LocalResourceManager that wraps the JFace resource manager (JFaceResource.getResources()) and use it to create any images I need. I can add a dispose listener to the control of the viewer that will dispose of the manager when the viewer is closed. This way, I don't need to ensure that I match each create with a dispose. I can just happily call create when I need an image, knowing that the manager will never create the same image twice and will dispose of them all when I call dispose on the manager.

There is another advantage of managing images this way. The image created from a LocalResourceManager for a particular descriptor is also pushed up to the parent manager(e.g. the JFace resource manager). This means that the image is accessible through the parent manager or through other local managers that share the same parent. This means that at most one image is created for a particular descriptor but the image will be disposed when it is no longer used anywhere.

ImageRegistry: An ImageRegistry wraps a ResourceManager and allows image descriptors and images to be referenced by a key of type String. Also, when creating an image registry, you can populate it with image descriptors and the registry will only create the corresponding image the first time it is referenced. Because an ImageRegistry wraps a ResourceManager, you get all those benefits as well. As with a ResourceManager, an ImageRegistry needs to be disposed of when the images in the registry are no longer needed and disposing a registry will free all the images in its resource manager if they are not used by another manager.

However, as Tod pointed out, one must be careful when adding images to either the JFace image registry (JFaceResources.getImageRegistry()) or the image registry of a plugin (AbstractUIPlugin#getImageRegistry()) since both of these registries are only disposed when the workbench is closed. I think a better approach would be to create ImageRegistries that are local to views and editors and have these registries wrap LocalResourceManagers so that the created images are shared when possible but are disposed when no longer in use.

Disclaimer: I started out as a Core level guy who has been thrust into this UI level stuff. It turns out that most of the image mangement code I've written up until this point has been done using a HashMap. I just recently stumbled on this API when fixing an image disposal problem. Given that 3.2 development on the Platform is pretty much frozen at this point, I'll need to wait until 3.3 before I can put this into practice (i.e. treat the above as ideas and discussion points instead of the carved-in-stone way to do image management).


Post a Comment

<< Home