Mercurial > projects > dwt-addons
diff dwtx/jface/resource/ImageRegistry.d @ 8:a3ff22a98bef
Dialog
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 29 Mar 2008 01:25:27 +0100 |
parents | |
children | ea8ff534f622 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/ImageRegistry.d Sat Mar 29 01:25:27 2008 +0100 @@ -0,0 +1,363 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 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> + */ +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 Object createResource(Device device) { + if (device is originalDisplay) { + refCount++; + return original; + } + return super.createResource(device); + } + + public 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 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$ + } + + // Should be checking for a null image here. + // Current behavior is that a null image won't be caught until dispose. + // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=130315 + 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) { + return cast(Entry) getTable().get(key); + } + + 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; + } +}