## User interface resources

The org.eclipse.jface.resource package defines classes that help plug-ins manage UI resources such as fonts and icons.

Many of the workbench extension points allow plug-ins to supply icons that can be used to show their contributions in the workbench. Since GUI operating systems support a limited number of images or fonts in memory at once, a plug-in's UI resources must be carefully managed and sometimes shared between widgets.

We've already seen several references to icons in the readme tool plug-in. Some of its icons are specified in the plugin.xml markup.

    <extension
       point="org.eclipse.ui.views">
    	<category
    	   id="org.eclipse.ui.examples.readmetool"
    	   name="%Views.category">
    	</category>
    	<view
    	   id="org.eclipse.ui.examples.readmetool.views.SectionsView"
    	   name="%Views.ReadmeSections"
    	   icon="icons/view16/sections.png"
    	   category="org.eclipse.ui.examples.readmetool"
    	   class="org.eclipse.ui.examples.readmetool.ReadmeSectionsView">
    	</view>
    </extension>

We've also seen code that describes images on the fly. The following is from the readme tool's ReadmeEditorActionBarContributor.

    public ReadmeEditorActionBarContributor() {
          	...
    	action1 = new EditorAction(MessageUtil.getString("Editor_Action1"));
    	action1.setToolTipText(MessageUtil.getString("Readme_Editor_Action1"));
    	action1.setDisabledImageDescriptor(ReadmeImages.EDITOR_ACTION1_IMAGE_DISABLE);
    	action1.setImageDescriptor(ReadmeImages.EDITOR_ACTION1_IMAGE_ENABLE);
    	...

JFace provides the basic support classes that allow plug-ins to manage their icons and fonts without worrying about when the corresponding platform graphics objects are created and destroyed. These support classes are used directly by plug-ins as shown above, or indirectly when the workbench uses these classes to obtain images that are described in extension point markup.

### Image descriptors and the registry

The SWT Image class represents an image from the operating system's perspective. Because most GUI operating systems have a limit on the number of images that can be open at once, plug-ins should be very careful when creating them, and ensure that they also dispose of them properly when finished using them. By using the JFace ImageDescriptor and ImageRegistry classes instead of the SWT image, plug-ins can generally avoid creating, managing, and disposing these images directly.

#### Image descriptor

The ImageDescriptor class can be used as a lightweight description of an image. It specifies everything that is needed to create an image, such as the URL or filename where the image can be obtained. ImageDescriptors do not allocate an actual platform image unless specifically requested using the createImage() method.

Image descriptors are the best strategy when your code is structured such that it defines all the icons in one place and allocates them as they are needed. Image descriptors can be created at any time without concern for OS resources, making it convenient to create them all in initialization code.

#### Image registry

The ImageRegistry class is used to keep a list of named images. Clients can add image descriptors or SWT images directly to the list. When an image is requested by name from the registry, the registry will return the image if it has been created, or create one from the descriptor. This allows clients of the registry to share images.

Images that are added to or retrieved from the registry must not be disposed by any client. The registry is responsible for disposing of the image since the images are shared by multiple clients. The registry will dispose of the images when the platform GUI system shuts down.

### Plug-in patterns for using images

#### Specifying the image in the plugin.xml

Where possible, specify the icon for your plug-in's UI objects in the plugin.xml file. Many of the workbench extension points include configuration parameters for an icon file. By defining your icons in your extension contribution in the plugin.xml, you leave the image management strategy up the platform. Since the icons are typically kept in your plug-in's directory, this allows you to specify the icons and manage the files all in one place.

The other patterns should only be considered when you can't specify the icon as part of your extension contribution.

#### Explicit creation

Explicitly creating an image is the best strategy when the image is infrequently used and not shared. The image can be created directly in SWT and disposed after it is used.

Images can also be created explicitly using an ImageDescriptor and invoking the createImage() method. As in the first case, the dispose() method for the image must be invoked after the image is no longer needed. For example, if a dialog creates an image when it is opened, it should dispose the image when it is closed.

#### Image registry

When an image is used frequently in a plug-in and shared across many different objects in the UI, it is useful to register the image descriptor with an ImageRegistry. The images in the registry will be shared with any object that queries an image by the same name. You must not dispose any images in the registry since they are shared by other objects.

Adding an image to the image registry is the best strategy when the image is used frequently, perhaps through the lifetime of the plug-in, and is shared by many objects. The disadvantage of using the registry is that images in the registry are not disposed until the GUI system shuts down. Since there is a limit on the number of platform (SWT) images that can be open at one time, plug-ins should be careful not to register too many icons in a registry.

The class AbstractUIPlugin includes protocol for creating a plug-in wide image registry.

#### Label providers

When an icon is used frequently to display items in a particular viewer, it can be shared among similar items in the viewer using a label provider. Since a label provider is responsible for returning an image for any object in a viewer, it can control the creation of the image and any sharing of images across objects in the viewer.

The label provider can use any of the previously discussed techniques to produce an image. If you browse the various implementations of getImage() in the LabelProvider subclasses, you will see a variety of approaches including caching a single icon for objects and maintaining a table of images by type. Images created by a label provider must be disposed in the provider's dispose() method, which is called when the viewer is disposed.

Using a label provider is a good compromise between explicit creation and the image registry. It promotes sharing of icons like the image registry, yet still maintains control over the creation and disposal of the actual image.

#### Plug-in wide image class

When fine-tuning a plug-in, it is common to experiment with all of these different image creation patterns. It can be useful to isolate the decision making regarding image creation in a separate class and instruct all clients to use the class to obtain all images. This way, the creation sequence can be tuned to reflect the actual performance characteristics of the plug-in.

### ImageCache

Managing images in applications can be a complex task. Because there is a limit on the number of images that can be in memory at any one time, improper usage of images can greatly harm an application's performance. There are several ways to handle image resources issues, such as using a global image registry. However, the image registry will only dispose the images when the SWT Display that creates them is disposed, potentially on shutdown. This implies that images might be kept in the registry longer than needed. For large scale applications, this can be a problem.

The ImageCache is a weakly referenced cache of equivalent image descriptors to arrays of image instances, representing normal, gray and disabled images. The cache is used to hold images in memory while their corresponding image descriptors are defined. When the image descriptors become weakly referred to, a cleaner thread disposes the corresponding images in the array of images.

The goal of the ImageCache is to partially remove the burden from the user to clean-up the images they request. The key concept behind the ImageCache is to rely on the garbage collector for image clean-up. The idea is to map weakly referenced image descriptors to images and dispose images when their corresponding image descriptors are not referenced anymore. The disposal of the images is performed by a cleaner thread and not by the user. The ImageCache is a centralized cache of shared images that will ensure uniqueness of images, as well as guaranteed image clean-up, either when the garbage collector determines that the image descriptors are no longer referenced, or on shut down by calling the ImageCache's dispose().

It is recommended to use this class as a singleton, since it creates a thread for image clean-up. Requesting images and disposing the ImageCache should be done via the UI Thread. Upon request of a disabled or gray image, the normal image will be created as well, if it was not already in the cache, in order to create the disabled or gray version of the image.

The ImageCache serves two main purposes: image retrieval and image clean-up. The image retrieval is performed by the getImage() methods that query the image map for the requested images. The image clean-up is performed by the image cleaner thread and the dispose() method when it is invoked.

- Image Retrieval: The ImageCache maps a set of weak references to equivalent image descriptors to the corresponding array of images (disabled, gray and regular images). When an image is requested for a particular image descriptor, the image map is queried for the corresponding equivalence set.
  - If no equivalence set for that image descriptor exists in the image map, the equivalence set, with the weak reference to the image descriptor added to the set, and the requested image are created and added to the image map. The newly created image is returned.
  - If an equivalence set corresponding to the passed image descriptor is found, a weak reference to that image descriptor is added to the set if a weak reference to the same image descriptor did not already exist. The requested image for the corresponding array of images is returned or is created if it had not been previously created. The image, newly created or from the cache, is returned.
- Image Clean-Up: The cleaner thread is started in the ImageCache's constructor. The thread monitors the reference queue for potential images to clean-up. When a weak reference is put into the reference queue, it is removed from its corresponding equivalence set in the image map. Once the equivalence set becomes empty, it is removed from the image map and the created images in its corresponding array of images are disposed.

Note: It is the responsibility of the user to ensure that the image descriptors are kept around as long as the images are needed, since the images will be disposed of with no warning when all descriptors associated with a particular array of images become weakly referenced. To avoid duplicate images, the user should ensure that equivalency in their implementation of image descriptors are properly defined. The users of this cache should not explicitly dispose the images themselves since they could be shared by other objects. This cache makes no guarantees on how long the cleaning process will take, or when exactly it will occur since it is dependent on when the garbage collector will run. It is, however, guaranteed that upon calling the ImageCache's dispose(), all images in the cache will be disposed immediately.

### Font registry

Fonts are another limited resource in platform operating systems. The creation and disposal issues are the same for fonts as for images, requiring similar speed/space tradeoffs. In general, fonts are allocated in SWT by requesting a font with a platform dependent font name.

The FontRegistry class keeps a table of fonts by their name. It manages the allocation and disposal of the font.

In general, plug-ins should avoid allocating any fonts or describing fonts with platform specific names. Although the font registry is used internally in JFace, it is typically not used by plug-ins. The JFaceResources class should be used to access common fonts.

It is very common to allow users to specify their preferences for the application's fonts in a preference page. In these cases, the FontFieldEditor should be used to obtain the font name from the user, and a FontRegistry may be used to keep the font. The FontFieldEditor is only used in preference pages.

### JFaceResources

The class JFaceResources controls access to common platform fonts and images. It maintains an internal font and image registry so that clients can share named fonts and images.

There are many techniques used in the workbench and other plug-ins to share images where required. The JFaceResources image registry is not widely used across the workbench and plug-in code.

Use of fonts is much simpler. The workbench and most plug-ins use the JFaceResources class to request fonts by logical name. Methods such as getDialogFont() and getDefaultFont() are provided so that plug-ins can use the expected fonts in their UI.