Friday, September 23, 2011

Eclipse RCP: All My Registries

Using SWT you have to care about your operating system resources such as fonts, colors and images.
Fortunately JFace provides you with a set of registries, for every resource one FontRegistry, ColorRegistry and ImageRegistry. The resources are created lazily when they get accessed and are disposed automatically when the display is disposed.
There are global registries but to avoid conflicting keys you should use private instances.

Here one Example of the usage of an ImageRegistry:
 ImageRegistry imgReg = new ImageRegistry();  
 imgReg.put("avatar", ImageDescriptor.createFromURL(  
    FileLocator.find(bundle, new Path("icons/avatar.jpg"), null)));  
 Image avatar = imgReg.get("avatar");  

You have to instantiate the registry locally, if you want to use it somewhere else you have to make a singleton for it.
The metod put(String key, ImageDescriptor descriptor) takes an ImageDescriptor as an argument, but your image files are normally located in your plugin. You have to get the bundle for the location.
Lot of stuff for just a picture.

Wouldn't it be more easy to have just one singleton for all the registries with lots of convenient methods that take care of alle the specialities like the location of your files?

Have a look at my Registries class:
 package org.strangewt.jface.resource;
/**  
  * Manages all Registries from JFace. <br>  
  * - ColorRegistry <br>  
  * - FontRegistry <br>  
  * - ImageRegistry <br>  
  * First use must be after the <code>Display</code> has been created, this can  
  * be usually done in the method <code>IApplication.start()</code> of the  
  * RCP-Bundles. Afterwards you can set up all your colors, fonts and images by  
  * passing over a derived Object from the <code>IRegistriesConfiguration</code>  
  * interface.  
  */  
 public class Registries {  
      protected static ColorRegistry colorReg;  
      protected static FontRegistry fontReg;  
      protected static ImageRegistry imgReg;  
      private static Bundle bundle;  
      private static Registries instance;  
      private Registries() {  
           colorReg = new ColorRegistry();  
           fontReg = new FontRegistry();  
           imgReg = new ImageRegistry();  
      }  
      /**  
       * Is used to determine the root folder of the application. Get the bundle  
       * from <code>Activator.getDefault().getBundle()</code>  
       */  
      public static Registries getInstance(Bundle bundle) {  
           Registries.bundle = bundle;  
           return getInstance();  
      }  
      public static Registries getInstance() {  
           if (instance == null) {  
                instance = new Registries();  
           }  
           return instance;  
      }  
      public Registries init(IRegistriesConfiguration configurator) {  
           configurator.configure(this);  
           return this;  
      }  
      /**  
       * @param path  
       *      for example icons/background.jpg  
       */  
      public void putImage(String key, String path) {  
           imgReg.put(key, ImageDescriptor.createFromURL(FileLocator.find(bundle,  
                     new Path(path), null)));  
      }  
      public void putImage(String key, Image image) {  
           imgReg.put(key, image);  
      }  
      public Image getImage(String key) {  
           return imgReg.get(key);  
      }  
      public ImageDescriptor getImageDescriptor(String key) {  
           return imgReg.getDescriptor(key);  
      }  
      public void putColor(String symbolicName, int red, int green, int blue) {
           colorReg.put(symbolicName, new RGB(red, green, blue));
      }
      public void putColor(String symbolicName, RGB colorData) {  
           colorReg.put(symbolicName, colorData);  
      }  
      /**  
       * @param hexColorStr  
       *      "00FF00"  
       */  
      public void putColor(String symbolicName, String hexColorStr) {  
           Integer colorValue = Integer.parseInt(hexColorStr, 16);  
           int red = (colorValue & 0xFF0000) >> 16;  
           int green = (colorValue & 0x00FF00) >> 8;  
           int blue = (colorValue & 0x0000FF);  
           putColor(symbolicName, new RGB(red, green, blue));  
      }  
      public Color getColor(String key) {  
           return colorReg.get(key);  
      }  
      /**  
       * Looks up the registry if there is a color for the key. If not, a new  
       * color is instanciated from the hex-representation.  
       */  
      public Color getColor(String key, String hexColorStr) {  
           Color color = colorReg.get(key);  
           if (color == null) {  
                putColor(key, hexColorStr);  
                color = colorReg.get(key);  
           }  
           return color;  
      }  
      public String getColorAsHex(String key) {  
           String hexColorStr = null;  
           Color color = getColor(key);  
           if (color != null) {  
                hexColorStr = toHex(color.getRGB());  
           }  
           return hexColorStr;  
      }  
      /**  
       * Converts the color of an <code>RGB</code> object into his hex values. <br>  
       * RGB(0,255,0) -> "00FF00"  
       */  
      public String toHex(RGB rgb) {  
           String hexColorStr = Integer.toHexString((rgb.red << 16)  
                     + (rgb.green << 8) + rgb.blue);  
           if (hexColorStr.length() == 4) {  
                hexColorStr = "00" + hexColorStr;  
           } else if (hexColorStr.length() == 2) {  
                hexColorStr = "0000" + hexColorStr;  
           }  
           return hexColorStr;  
      }  
      public void putFont(String symbolicName, FontData fontData) {
           fontReg.put(symbolicName, new FontData[] {fontData});
      }
      public void putFont(String symbolicName, FontData fontData[]) {  
           fontReg.put(symbolicName, fontData);  
      }  
      public Font getFont(String key) {  
           return fontReg.get(key);  
      }  
 }  

The configuration interface:
 package org.strangewt.jface.resource;  
 public interface IRegistriesConfiguration {  
      /**  
       * Gets passed over to the <code>Registries</code> where it is used to  
       * configure it self. Typical content: <br>  
       * mr.putColor("active element", new RGB(0, 255, 0)); <br>  
       * mr.putImage("dialog.header", "icons/background.jpg"); <br>  
       * mr.putFont("view.headline", new FontData[] { new FontData("Tahoma", 10,  
       * SWT.BOLD) });  
       */  
      public void configure(Registries registries);  
 }  

To use it, you have to derive the interface and define your resources. Look how easy it is to put an image into the registry.
 public class DemoRegistriesConfiguration implements IRegistriesConfiguration {  
      @Override  
      public void configure(Registries r) {  
           r.putColor("red", 255, 0, 0);  
           r.putImage("avatar", "/icons/avatar_strangeoptics.jpg");  
           r.putFont("courier_bold", new FontData("Courier",10,SWT.BOLD));  
      }  
 }  

Then you have to instantiat the Registries class. Best location in the Aplication.start() method right after the Display is created.

Display display = PlatformUI.createDisplay();  
Registries.getInstance(Activator.getDefault().getBundle()).init(
new DemoRegistriesConfiguration());  

Now you can use the image everywhere in your code.

 Registries.getInstance().getImage("avatar")  

The source code is available in my svn repository at google code.

No comments:

Post a Comment