All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.resource.ImageRegistry Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Steven Ketcham ([email protected]) - Bug 42451
 *     [Dialogs] ImageRegistry throws null pointer exception in
 *     application with multiple Display's
 *******************************************************************************/
package org.eclipse.jface.resource;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.pde.api.tools.annotations.NoExtend;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Display;

/**
 * An image registry maintains a mapping between symbolic image names
 * and SWT image objects or special image descriptor objects which
 * defer the creation of SWT image objects until they are needed.
 * 

* An image registry owns all of the image objects registered * with it, and automatically disposes of them when the SWT 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. *

*

* Clients may instantiate this class (it was not designed to be subclassed). *

*

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

*/ @NoExtend public class ImageRegistry { /** * display used when getting images */ private Display display; private ResourceManager manager; private Map table; private Runnable disposeRunnable = this::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 extends 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 OriginalImageDescriptor(Image original, Device originalDisplay) { this.original = original; this.originalDisplay = originalDisplay; } @Override public Object createResource(Device device) throws DeviceResourceException { if (device == originalDisplay) { refCount++; return original; } return super.createResource(device); } @Override public void destroyResource(Object toDispose) { if (original == toDispose) { refCount--; if (refCount == 0) { original.dispose(); original = null; } } else { super.destroyResource(toDispose); } } @Override public ImageData getImageData(int zoom) { return original.getImageData(zoom); } } /** * Creates an empty image registry. *

* There must be an SWT Display created in the current * thread before calling this method. *

*/ public ImageRegistry() { 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 ImageRegistry(ResourceManager manager) { Assert.isNotNull(manager); Device dev = manager.getDevice(); if (dev instanceof Display) { this.display = (Display)dev; } this.manager = manager; manager.disposeExec(disposeRunnable); } /** * Creates an empty image registry. * * @param display this Display must not be * null and must not be disposed in order * to use this registry */ public ImageRegistry(Display display) { this(JFaceResources.getResources(display)); } /** * Returns the image associated with the given key in this registry, * or null if none. * * @param key the key * @return the image, or null if none */ @SuppressWarnings({ "removal", "deprecation" }) public Image get(String key) { // can be null if (key == null) { return null; } if (display != 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 SWT will dispose. * * Applications should go direclty to SWT for these icons. * * @see Display.getSystemIcon(int ID) */ int swtKey = -1; if (key.equals(Dialog.DLG_IMG_INFO)) { swtKey = SWT.ICON_INFORMATION; } if (key.equals(Dialog.DLG_IMG_QUESTION)) { swtKey = SWT.ICON_QUESTION; } if (key.equals(Dialog.DLG_IMG_WARNING)) { swtKey = SWT.ICON_WARNING; } if (key.equals(Dialog.DLG_IMG_ERROR)) { swtKey = SWT.ICON_ERROR; } // if we actually just want to return an SWT image do so without // looking in the registry if (swtKey != -1) { final Image[] image = new Image[1]; final int id = swtKey; display.syncExec(() -> image[0] = display.getSystemImage(id)); return image[0]; } } Entry entry = getEntry(key); if (entry == null) { return null; } if (entry.image == null) { entry.image = manager.createImageWithDefault(entry.descriptor); } return entry.image; } /** * Returns the descriptor associated with the given key in this registry, * or null if none. * * @param key the key * @return the descriptor, or null if none * @since 2.1 */ public ImageDescriptor getDescriptor(String key) { Entry entry = getEntry(key); if (entry == 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 * ImageDescriptor.createImage) 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 == null) { entry = new Entry(); getTable().put(key, entry); } if (entry.image != 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. *

* Note that an image registry owns all of the image objects registered * with it, and automatically disposes of them when the SWT Display is disposed. * Because of this, clients must not register an image object * that is managed by another object. *

* * @param key the key * @param image the image, should not be null * @exception IllegalArgumentException if the key already exists */ public void put(String key, Image image) { Entry entry = getEntry(key); if (entry == null) { entry = new Entry(); putEntry(key, entry); } if (entry.image != null || entry.descriptor != 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 SWT 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 != null) { manager.destroy(descriptor); getTable().remove(key); } } private Entry getEntry(String key) { return getTable().get(key); } private void putEntry(String key, Entry entry) { getTable().put(key, entry); } private Map getTable() { if (table == null) { table = new HashMap<>(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 != null) { for (Entry entry : table.values()) { if (entry.image != null) { manager.destroy(entry.descriptor); } } table = null; } display = null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy