Recursos de la interfaz de usuario

El paquete org.eclipse.jface.resource define clases que ayudan a los conectores a gestionar recursos de la UI, como los fonts y los iconos.

Muchos de los puntos de extensión del entorno de trabajo permiten a los conectores suministrar iconos que pueden utilizarse para mostrar sus contribuciones en el entorno de trabajo. Puesto que los sistemas operativos de la GUI dan soporte a un número limitado de imágenes o fonts en la memoria a la vez, los recursos de la UI de los conectores deben gestionarse con precaución y a veces compartirse entre los widgets.

Ya hemos visto varias referencias a los iconos en el conector de la herramienta readme. Algunos de estos iconos están especificados en los códigos XML del archivo plugin.xml.

<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>

También hemos visto código que describe las imágenes sobre la marcha. El código siguiente procede del objeto ReadmeEditorActionBarContributor de la herramienta readme.

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 proporciona las clases de soporte básico que permiten a los conectores gestionar sus iconos y fonts sin preocuparse de cuándo se crean y destruyen los correspondientes objetos gráficos de la plataforma. Estas clases de soporte las utilizan directamente los conectores, tal como se ha mostrado anteriormente, o indirectamente cuando el entorno de trabajo utiliza estas clases para obtener las imágenes descritas en los códigos XML del punto de extensión.

Los descriptores de imágenes y el registro de imágenes

La clase Image de SWT representa una imagen desde el punto de vista del sistema operativo. Puesto que la mayoría de sistemas operativos de la GUI tienen un número limitado de imágenes que pueden abrirse a la vez, los conectores deben actuar con precaución al crearlas y asegurarse de desecharlas adecuadamente cuando ya no se necesitan. Si utilizan las clases ImageDescriptor y ImageRegistry de JFace, en lugar de la imagen de SWT, los conectores pueden en general evitar crear, gestionar y desechar estas imágenes directamente.

Descriptores de imágenes

La clase ImageDescriptor funciona a modo de descripción ligera de una imagen. Especifica todo lo que se necesita para crear una imagen, como el URL o el nombre del archivo en el que se puede obtener la imagen. ImageDescriptors no asigna una imagen de plataforma real a menos que se solicite de manera específica mediante el método createImage().

Los descriptores de imágenes son la mejor estrategia cuando el código está estructurado de tal manera que define todos los iconos en un lugar y los asigna a medida que se necesitan. Los descriptores de imágenes se pueden crear en cualquier momento sin preocuparse de los recursos del sistema operativo, por lo que resulta práctico crearlos todos en el código de inicialización.

Registro de imágenes

La clase ImageRegistry permite conservar una lista de imágenes con nombre. Los clientes pueden añadir descriptores de imágenes o imágenes de SWT directamente a la lista. Cuando se solicita al registro una imagen por su nombre, el registro devolverá la imagen si está creada o bien creará una a partir del descriptor. Esto permite a los clientes del registro compartir las imágenes.

Ningún cliente debe desechar las imágenes que se hayan añadido al registro o recuperado a partir de él. Es el registro el encargado de desechar las imágenes, porque hay múltiples clientes que las comparten. El registro desechará las imágenes cuando se concluya el sistema de la GUI de la plataforma.

Patrones de conectores para utilizar imágenes

Especificar la imagen en el archivo plugin.xml

Siempre que sea posible, especifique el icono de los objetos de la UI del conector en el archivo plugin.xml. Muchos de los puntos de extensión del entorno de trabajo incluyen parámetros de configuración para un archivo de icono. Al definir sus iconos en la contribución de extensión del archivo plugin.xml, deja que sea la plataforma la que se encargue de la estrategia de gestión de imágenes. Puesto que los iconos suelen conservarse en el directorio del conector, esto le permite especificar los iconos y gestionar todos los archivos en un solo lugar.

Los demás patrones solo deben tenerse en cuenta cuando no pueda especificar el icono como parte de la contribución de extensión.

Creación explícita

Crear una imagen explícitamente es la mejor estrategia cuando la imagen se utiliza con poca frecuencia y no se comparte. La imagen se puede crear directamente en SWT y desecharse una vez utilizada.

Las imágenes también se pueden crear de manera explícita utilizando un descriptor de imagen (ImageDescriptor) e invocando el método createImage(). Al igual que en el primer caso, hay que llamar al método dispose() de la imagen cuando ésta ya no sea necesaria.  Por ejemplo, si un diálogo crea una imagen cuando se abre, deberá desecharla cuando se cierre.

Registro de imágenes

Cuando una imagen se utiliza con frecuencia en un conector y se comparte con muchos objetos distintos de la UI, es de utilidad registrar el descriptor de la imagen en un registro de imágenes (ImageRegistry). Las imágenes del registro se compartirán con los objetos que consulten una imagen especificando el mismo nombre. No debe desechar ninguna imagen del registro porque hay otros objetos que la comparten.

La adición de una imagen al registro de imágenes es la mejor estrategia cuando la imagen se utiliza con frecuencia, tal vez a lo largo de la vida del conector, y hay muchos objetos que la comparten. El inconveniente de utilizar el registro es que las imágenes del registro no se desechan hasta que se concluye el sistema de la GUI. El número de imágenes de la plataforma (SWT) que pueden estar abiertas en un momento dado es limitado, y por ello los conectores deben actuar con precaución para no registrar demasiados iconos en un registro.

La clase AbstractUIPlugin incluye un protocolo para crear un registro de imágenes a escala de conector.

Proveedores de etiquetas

Cuando un icono se utiliza con frecuencia para visualizar los elementos de un visor concreto, se puede compartir entre los elementos similares del visor mediante un proveedor de etiquetas. Puesto que el proveedor de etiquetas es el responsable de devolver una imagen para cualquier objeto del visor, puede controlar la creación de la imagen y el compartimiento de las imágenes entre los objetos del visor.

El proveedor de etiquetas puede utilizar cualquiera de las técnicas explicadas anteriormente para producir una imagen. Si examina las diversas implementaciones del método getImage() de las subclases de LabelProvider, verá una gran variedad de enfoques, como el de almacenar en antememoria un solo icono para los objetos y el de mantener una tabla de imágenes por tipo.  Las imágenes creadas por un proveedor de etiquetas deben desecharse en el método dispose() del proveedor, al que se llama cuando se desecha el visor.

La utilización de un proveedor de etiquetas es un buen compromiso entre la creación explícita y el registro de imágenes. Promociona el compartimiento de iconos, como el registro de imágenes, sin dejar de mantener el control sobre las tareas de crear y desechar la imagen real.

Clase de imagen a escala de conector

Cuando se realiza un ajuste más preciso del conector, se suelen probar todos estos patrones distintos de creación de imágenes. Puede ser de utilidad aislar la toma de decisiones sobre la creación de imágenes en una clase aparte e indicar a todos los clientes que utilicen dicha clase para obtener todas las imágenes. De esta manera, la secuencia de creación se puede ajustar de tal manera que refleje las características del rendimiento real del conector. 

ResourceManager

La clase ResourceManager se utiliza para mantener una correlación de los ImageDescriptor con imágenes (Image), de tal manera que una imagen puede volver a utilizarse haciendo referencia a la misma mediante su descriptor. Cuando el descriptor solicita una imagen del registro, éste devolverá la imagen si se ha creado o creará una del descriptor. Esto permite a los clientes del registro compartir las imágenes.

El ResourceManager de nivel superior es un DeviceResourceManager que se crea en una pantalla. El ResourceManager definido por JFaceResources.getResources() es un DeviceResourceManager y puede utilizarse como ResourceManager de nivel superior. Si necesita un ResourceManager con un ciclo de vida más corto que el DeviceResourceManager, puede crear un LocalResourceManager como hijo y y desecharlo cuando haya acabado de trabajar con él.

Se desechará un DeviceResourceManager cuando la pantalla utilizada para crearla se deseche, de manera que no sea necesario ningún código de gestión especial.

Ningún cliente debe desechar las imágenes que se hayan añadido al gestor o recuperado de él. El gestor es el responsable de desechar la imagen, porque hay varios clientes que la comparten. El registro desechará las imágenes cuando se deseche el ResourceManager que las retiene.

Registro de fonts

Los fonts son otro recurso limitado en los sistemas operativos de la plataforma. Los problemas que presentan las tareas de crear y desechar son los mismos para los fonts que para las imágenes, por lo que también habrá que negociar entre la velocidad y el espacio. En SWT, los fonts se suelen asignar solicitándolos con un nombre dependiente de la plataforma.

La clase FontRegistry conserva una tabla de fonts por su nombre. Gestiona las tareas de asignar y desechar los fonts.

En general, los conectores deben evitar asignar o describir los fonts con nombres específicos de la plataforma. En JFace, el registro de fonts se utiliza internamente, pero los conectores no suelen utilizarlo. Hay que utilizar la clase JFaceResources para acceder a los fonts comunes.

Es muy habitual permitir que los usuarios especifiquen sus preferencias para los fonts de la aplicación en una página de preferencias.  En estos casos, hay que utilizar la clase FontFieldEditor para obtener el nombre del font a partir del usuario, y puede utilizarse un registro de fonts (clase FontRegistry) para conservar el font.  La clase FontFieldEditor solo se utiliza en las páginas de preferencias.

JFaceResources

La clase JFaceResources controla el acceso a los fonts e imágenes comunes de la plataforma. Mantiene un registro interno de los fonts e imágenes para que los clientes puedan compartir los fonts y las imágenes con nombre.

En el entorno de trabajo y en otros conectores se utilizan muchas técnicas para compartir las imágenes donde se necesite. La utilización del registro de imágenes de JFaceResources no está muy extendida en el código del entorno de trabajo ni en el de los conectores.

La utilización de fonts es mucho más simple. El entorno de trabajo y la mayoría de los conectores utilizan la clase JFaceResources para solicitar fonts por su nombre lógico. Se proporcionan métodos, como getDialogFont() y getDefaultFont(), para que los conectores puedan utilizar los fonts esperados de su UI.