Mercurial > projects > dwt-addons
view dwtx/jface/resource/ImageRegistry.d @ 90:7ffeace6c47f
Update 3.4M7 to 3.4
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 06 Jul 2008 23:30:07 +0200 |
parents | 46a6e0e6ccd4 |
children | 04b47443bb01 |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Steven Ketcham (sketcham@dsicdi.com) - Bug 42451 * [Dialogs] ImageRegistry throws null pointer exception in * application with multiple Display's * Port to the D programming language: * Frank Benoit <benoit@tionex.de> *******************************************************************************/ module dwtx.jface.resource.ImageRegistry; import dwtx.jface.resource.ImageDescriptor; import dwtx.jface.resource.ResourceManager; import dwtx.jface.resource.DeviceResourceException; import dwtx.jface.resource.JFaceResources; import tango.util.collection.HashMap; import tango.util.collection.model.Map; // import java.util.Iterator; // import java.util.Map; import dwt.DWT; import dwt.graphics.Device; import dwt.graphics.Image; import dwt.graphics.ImageData; import dwt.widgets.Display; import dwtx.core.runtime.Assert; import dwtx.jface.dialogs.Dialog; import dwt.dwthelper.utils; import dwt.dwthelper.Runnable; /** * An image registry maintains a mapping between symbolic image names * and DWT image objects or special image descriptor objects which * defer the creation of DWT image objects until they are needed. * <p> * An image registry owns all of the image objects registered * with it, and automatically disposes of them when the DWT Display * that creates the images is disposed. Because of this, clients do not * need to (indeed, must not attempt to) dispose of these images themselves. * </p> * <p> * Clients may instantiate this class (it was not designed to be subclassed). * </p> * <p> * Unlike the FontRegistry, it is an error to replace images. As a result * there are no events that fire when values are changed in the registry * </p> * @noextend This class is not intended to be subclassed by clients. */ public class ImageRegistry { /** * display used when getting images */ private Display display; private ResourceManager manager; private Map!(String,Entry) table; private Runnable disposeRunnable; private void init_disposeRunnable(){ disposeRunnable = new class Runnable { public void run() { dispose(); } }; } /** * Contains the data for an entry in the registry. */ private static class Entry { /** the image */ protected Image image; /** the descriptor */ protected ImageDescriptor descriptor; } private static class OriginalImageDescriptor : ImageDescriptor { private Image original; private int refCount = 0; private Device originalDisplay; /** * @param original the original image * @param originalDisplay the device the image is part of */ public this(Image original, Device originalDisplay) { this.original = original; this.originalDisplay = originalDisplay; } public override Object createResource(Device device) { if (device is originalDisplay) { refCount++; return original; } return super.createResource(device); } public override void destroyResource(Object toDispose) { if (original is toDispose) { refCount--; if (refCount is 0) { original.dispose(); original = null; } } else { super.destroyResource(toDispose); } } /* (non-Javadoc) * @see dwtx.jface.resource.ImageDescriptor#getImageData() */ public override ImageData getImageData() { return original.getImageData(); } } /** * Creates an empty image registry. * <p> * There must be an DWT Display created in the current * thread before calling this method. * </p> */ public this() { this(Display.getCurrent()); } /** * Creates an empty image registry using the given resource manager to allocate images. * * @param manager the resource manager used to allocate images * * @since 3.1 */ public this(ResourceManager manager) { init_disposeRunnable(); Assert.isNotNull(manager); Device dev = manager.getDevice(); if ( auto disp = cast(Display)dev ) { this.display = disp; } this.manager = manager; manager.disposeExec(disposeRunnable); } /** * Creates an empty image registry. * * @param display this <code>Display</code> must not be * <code>null</code> and must not be disposed in order * to use this registry */ public this(Display display) { this(JFaceResources.getResources(display)); } /** * Returns the image associated with the given key in this registry, * or <code>null</code> if none. * * @param key the key * @return the image, or <code>null</code> if none */ public Image get(String key) { // can be null if (key is null) { return null; } if (display !is null) { /** * NOTE, for backwards compatibility the following images are supported * here, they should never be disposed, hence we explicitly return them * rather then registering images that DWT will dispose. * * Applications should go direclty to DWT for these icons. * * @see Display.getSystemIcon(int ID) */ int swtKey = -1; if (key.equals(Dialog.DLG_IMG_INFO)) { swtKey = DWT.ICON_INFORMATION; } if (key.equals(Dialog.DLG_IMG_QUESTION)) { swtKey = DWT.ICON_QUESTION; } if (key.equals(Dialog.DLG_IMG_WARNING)) { swtKey = DWT.ICON_WARNING; } if (key.equals(Dialog.DLG_IMG_ERROR)) { swtKey = DWT.ICON_ERROR; } // if we actually just want to return an DWT image do so without // looking in the registry if (swtKey !is -1) { Image[1] image; int id = swtKey; display.syncExec(new class Runnable { public void run() { image[0] = display.getSystemImage(id); } }); return image[0]; } } Entry entry = getEntry(key); if (entry is null) { return null; } if (entry.image is null) { entry.image = manager.createImageWithDefault(entry.descriptor); } return entry.image; } /** * Returns the descriptor associated with the given key in this registry, * or <code>null</code> if none. * * @param key the key * @return the descriptor, or <code>null</code> if none * @since 2.1 */ public ImageDescriptor getDescriptor(String key) { Entry entry = getEntry(key); if (entry is null) { return null; } return entry.descriptor; } /** * Adds (or replaces) an image descriptor to this registry. The first time * this new entry is retrieved, the image descriptor's image will be computed * (via </code>ImageDescriptor.createImage</code>) and remembered. * This method replaces an existing image descriptor associated with the * given key, but fails if there is a real image associated with it. * * @param key the key * @param descriptor the ImageDescriptor * @exception IllegalArgumentException if the key already exists */ public void put(String key, ImageDescriptor descriptor) { Entry entry = getEntry(key); if (entry is null) { entry = new Entry(); getTable().add(key, entry); } if (entry.image !is null) { throw new IllegalArgumentException( "ImageRegistry key already in use: " ~ key); //$NON-NLS-1$ } entry.descriptor = descriptor; } /** * Adds an image to this registry. This method fails if there * is already an image or descriptor for the given key. * <p> * Note that an image registry owns all of the image objects registered * with it, and automatically disposes of them when the DWT Display is disposed. * Because of this, clients must not register an image object * that is managed by another object. * </p> * * @param key the key * @param image the image, should not be <code>null</code> * @exception IllegalArgumentException if the key already exists */ public void put(String key, Image image) { Entry entry = getEntry(key); if (entry is null) { entry = new Entry(); putEntry(key, entry); } if (entry.image !is null || entry.descriptor !is null) { throw new IllegalArgumentException( "ImageRegistry key already in use: " ~ key); //$NON-NLS-1$ } // Check for a null image here, otherwise the problem won't appear // until dispose. // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=130315 Assert.isNotNull(image, "Cannot register a null image."); //$NON-NLS-1$ entry.image = image; entry.descriptor = new OriginalImageDescriptor(image, manager.getDevice()); try { manager.create(entry.descriptor); } catch (DeviceResourceException e) { } } /** * Removes an image from this registry. * If an DWT image was allocated, it is disposed. * This method has no effect if there is no image or descriptor for the given key. * @param key the key */ public void remove(String key) { ImageDescriptor descriptor = getDescriptor(key); if (descriptor !is null) { manager.destroy(descriptor); getTable().removeKey(key); } } private Entry getEntry(String key) { auto tbl = getTable(); return cast(Entry) ( tbl.containsKey(key) ? tbl.get(key) : null ); } private void putEntry(String key, Entry entry) { getTable().add(key, entry); } private Map!(String,Entry) getTable() { if (table is null) { table = new HashMap!(String,Entry)/+(10)+/; } return table; } /** * Disposes this image registry, disposing any images * that were allocated for it, and clearing its entries. * * @since 3.1 */ public void dispose() { manager.cancelDisposeExec(disposeRunnable); if (table !is null) { foreach( key,entry; table ){ if (entry.image !is null) { manager.destroyImage(entry.descriptor); } } table = null; } display = null; } }