/******************************************************************************* * Copyright (c) 2006, 2015 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 * Lars Vogel <Lars.Vogel@vogella.com> - Bug 440270 *******************************************************************************/ package org.eclipse.jface.fieldassist; import java.util.HashMap; import java.util.Iterator; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.graphics.Image; /** * FieldDecorationRegistry is a common registry used to define shared field * decorations within an application. Unlike resource registries, the * FieldDecorationRegistry does not perform any lifecycle management of the * decorations. * </p> * <p> * Clients may specify images for the decorations in several different ways. * Images may be described by their image id in a specified * {@link ImageRegistry}. In this case, the life cycle of the image is managed * by the image registry, and the decoration registry will not attempt to obtain * an image from the image registry until the decoration is actually requested. * In cases where the client has access to an already-created image, the image * itself can be specified when registering the decoration. In this case, the * life cycle should be managed by the specifying client. * </p> * * @see FieldDecoration * @see ImageRegistry * * @since 3.2 */ public class FieldDecorationRegistry { /** * Decoration id for the decoration that should be used to cue the user that * content proposals are available. */ public static final String DEC_CONTENT_PROPOSAL = "DEC_CONTENT_PROPOSAL"; //$NON-NLS-1$ /** * Decoration id for the decoration that should be used to cue the user that * a field is required. */ public static final String DEC_REQUIRED = "DEC_REQUIRED"; //$NON-NLS-1$ /** * Decoration id for the decoration that should be used to cue the user that * a field has an error. */ public static final String DEC_ERROR = "DEC_ERROR"; //$NON-NLS-1$ /** * Decoration id for the decoration that should be used to cue the user that * a field has a warning. */ public static final String DEC_WARNING = "DEC_WARNING"; //$NON-NLS-1$ /** * Decoration id for the decoration that should be used to cue the user that * a field has additional information. * * @since 3.3 */ public static final String DEC_INFORMATION = "DEC_INFORMATION"; //$NON-NLS-1$ /** * Decoration id for the decoration that should be used to cue the user that * a field has an error with quick fix available. * * @since 3.3 */ public static final String DEC_ERROR_QUICKFIX = "DEC_ERRORQUICKFIX"; //$NON-NLS-1$ /* * Image id's */ private static final String IMG_DEC_FIELD_CONTENT_PROPOSAL = "org.eclipse.jface.fieldassist.IMG_DEC_FIELD_CONTENT_PROPOSAL"; //$NON-NLS-1$ private static final String IMG_DEC_FIELD_REQUIRED = "org.eclipse.jface.fieldassist.IMG_DEC_FIELD_REQUIRED"; //$NON-NLS-1$ private static final String IMG_DEC_FIELD_ERROR = "org.eclipse.jface.fieldassist.IMG_DEC_FIELD_ERROR"; //$NON-NLS-1$ private static final String IMG_DEC_FIELD_ERROR_QUICKFIX = "org.eclipse.jface.fieldassist.IMG_DEC_FIELD_ERROR_QUICKFIX"; //$NON-NLS-1$ private static final String IMG_DEC_FIELD_WARNING = "org.eclipse.jface.fieldassist.IMG_DEC_FIELD_WARNING"; //$NON-NLS-1$ private static final String IMG_DEC_FIELD_INFO = "org.eclipse.jface.fieldassist.IMG_DEC_FIELD_INFO"; //$NON-NLS-1$ /* * Declare images and decorations immediately. */ static { ImageRegistry imageRegistry = JFaceResources.getImageRegistry(); // Define the images used in the standard decorations. imageRegistry.put(IMG_DEC_FIELD_CONTENT_PROPOSAL, ImageDescriptor .createFromFile(FieldDecorationRegistry.class, "images/contassist_ovr.png"));//$NON-NLS-1$ imageRegistry.put(IMG_DEC_FIELD_ERROR, ImageDescriptor.createFromFile( FieldDecorationRegistry.class, "images/error_ovr.png"));//$NON-NLS-1$ imageRegistry.put(IMG_DEC_FIELD_WARNING, ImageDescriptor .createFromFile(FieldDecorationRegistry.class, "images/warn_ovr.png"));//$NON-NLS-1$ imageRegistry.put(IMG_DEC_FIELD_REQUIRED, ImageDescriptor .createFromFile(FieldDecorationRegistry.class, "images/required_field_cue.png"));//$NON-NLS-1$ imageRegistry.put(IMG_DEC_FIELD_ERROR_QUICKFIX, ImageDescriptor .createFromFile(FieldDecorationRegistry.class, "images/errorqf_ovr.png"));//$NON-NLS-1$ imageRegistry.put(IMG_DEC_FIELD_INFO, ImageDescriptor .createFromFile(FieldDecorationRegistry.class, "images/info_ovr.png"));//$NON-NLS-1$ // Define the standard decorations. Some do not have standard // descriptions. Use null in these cases. getDefault() .registerFieldDecoration( DEC_CONTENT_PROPOSAL, JFaceResources .getString("FieldDecorationRegistry.contentAssistMessage"), //$NON-NLS-1$ IMG_DEC_FIELD_CONTENT_PROPOSAL, imageRegistry); getDefault().registerFieldDecoration( DEC_ERROR, JFaceResources .getString("FieldDecorationRegistry.errorMessage"), //$NON-NLS-1$ IMG_DEC_FIELD_ERROR, imageRegistry); getDefault().registerFieldDecoration( DEC_ERROR_QUICKFIX, JFaceResources .getString("FieldDecorationRegistry.errorQuickFixMessage"), //$NON-NLS-1$ IMG_DEC_FIELD_ERROR_QUICKFIX, imageRegistry); getDefault().registerFieldDecoration(DEC_WARNING, null, IMG_DEC_FIELD_WARNING, imageRegistry); getDefault().registerFieldDecoration(DEC_INFORMATION, null, IMG_DEC_FIELD_INFO, imageRegistry); getDefault() .registerFieldDecoration( DEC_REQUIRED, JFaceResources .getString("FieldDecorationRegistry.requiredFieldMessage"), //$NON-NLS-1$ IMG_DEC_FIELD_REQUIRED, imageRegistry); } /* * Data structure that holds onto the decoration image info and description, * and can produce a decorator on request. */ class Entry { private String description; private String imageId; private ImageRegistry imageRegistry; private Image image; private FieldDecoration decoration; Entry(String description, String imageId, ImageRegistry registry) { this.description = description; this.imageId = imageId; this.imageRegistry = registry; } Entry(String description, Image image) { this.description = description; this.image = image; } FieldDecoration getDecoration() { if (decoration == null) { if (image == null) { if (imageRegistry == null) { imageRegistry = JFaceResources.getImageRegistry(); } image = imageRegistry.get(imageId); } decoration = new FieldDecoration(image, description); } // Null out all other fields now that the decoration has an image description = null; imageId = null; imageRegistry = null; image = null; return decoration; } } /** * Default instance of the registry. Applications may install their own * registry. */ private static FieldDecorationRegistry defaultInstance; /** * Maximum width and height used by decorations in this registry. Clients * may use these values to reserve space in dialogs for decorations or to * adjust layouts so that decorated and non-decorated fields line up. */ private int maxDecorationWidth = 0; private int maxDecorationHeight = 0; private HashMap<String, Entry> decorations = new HashMap<>(); /** * Get the default FieldDecorationRegistry. * * @return the singleton FieldDecorationRegistry that is used to manage * shared field decorations. */ public static FieldDecorationRegistry getDefault() { if (defaultInstance == null) { defaultInstance = new FieldDecorationRegistry(); } return defaultInstance; } /** * Set the default FieldDecorationRegistry. * * @param defaultRegistry * the singleton FieldDecorationRegistry that is used to manage * shared field decorations. */ public static void setDefault(FieldDecorationRegistry defaultRegistry) { defaultInstance = defaultRegistry; } /** * Construct a FieldDecorationRegistry. */ public FieldDecorationRegistry() { maxDecorationWidth = 0; maxDecorationHeight = 0; } /** * Get the maximum width (in pixels) of any decoration retrieved so far in * the registry. This value changes as decorations are added and retrieved. * This value can be used by clients to reserve space or otherwise compute * margins when aligning non-decorated fields with decorated fields. * * @return the maximum width in pixels of any accessed decoration */ public int getMaximumDecorationWidth() { return maxDecorationWidth; } /** * Get the maximum height (in pixels) of any decoration retrieved so far in * the registry. This value changes as decorations are added and retrieved. * This value can be used by clients to reserve space or otherwise compute * margins when aligning non-decorated fields with decorated fields. * * * @return the maximum height in pixels of any accessed decoration */ public int getMaximumDecorationHeight() { return maxDecorationHeight; } /** * Registers a field decoration using the specified id. The lifecyle of the * supplied image should be managed by the client. That is, it will never be * disposed by this registry and the decoration should be removed from the * registry if the image is ever disposed elsewhere. * * @param id * the String id used to identify and access the decoration. * @param description * the String description to be used in the decoration, or * <code>null</code> if the decoration has no description. * @param image * the image to be used in the decoration */ public void registerFieldDecoration(String id, String description, Image image) { decorations.put(id, new Entry(description, image)); // Recompute the maximums since this might be a replacement recomputeMaximums(); } /** * Registers a field decoration using the specified id. An image id of an * image located in the default JFaceResources image registry is supplied. * The image will not be created until the decoration is requested. * * @param id * the String id used to identify and access the decoration. * @param description * the String description to be used in the decoration, or * <code>null</code> if the decoration has no description. * * @param imageId * the id of the image in the JFaceResources image registry that * is used for this decorator */ public void registerFieldDecoration(String id, String description, String imageId) { decorations.put(id, new Entry(description, imageId, JFaceResources .getImageRegistry())); // Recompute the maximums as this could be a replacement of a previous // image. recomputeMaximums(); } /** * Registers a field decoration using the specified id. An image id and an * image registry are supplied. The image will not be created until the * decoration is requested. * * @param id * the String id used to identify and access the decoration. * @param description * the String description to be used in the decoration, or * <code>null</code> if the decoration has no description. * * @param imageId * the id of the image in the supplied image registry that is * used for this decorator * @param imageRegistry * the registry used to obtain the image */ public void registerFieldDecoration(String id, String description, String imageId, ImageRegistry imageRegistry) { decorations.put(id, new Entry(description, imageId, imageRegistry)); // Recompute the maximums since this could be a replacement recomputeMaximums(); } /** * Unregisters the field decoration with the specified id. No lifecycle * management is performed on the decoration's image. This message has no * effect if no field decoration with the specified id was previously * registered. * </p> * <p> * This method need not be called if the registered decoration's image is * managed in an image registry. In that case, leaving the decoration in the * registry will do no harm since the image will remain valid and will be * properly disposed when the application is shut down. This method should * be used in cases where the caller intends to dispose of the image * referred to by the decoration, or otherwise determines that the * decoration should no longer be used. * * @param id * the String id of the decoration to be unregistered. */ public void unregisterFieldDecoration(String id) { decorations.remove(id); recomputeMaximums(); } /** * Returns the field decoration registered by the specified id . * * @param id * the String id used to access the decoration. * @return the FieldDecoration with the specified id, or <code>null</code> * if there is no decoration with the specified id. */ public FieldDecoration getFieldDecoration(String id) { Object entry = decorations.get(id); if (entry == null) { return null; } return ((Entry) entry).getDecoration(); } /* * The maximum decoration width and height must be recomputed. Typically * called in response to adding, removing, or replacing a decoration. */ private void recomputeMaximums() { Iterator<Entry> entries = decorations.values().iterator(); maxDecorationHeight = 0; maxDecorationWidth = 0; while (entries.hasNext()) { Image image = entries.next().getDecoration().getImage(); if (image != null) { maxDecorationHeight = Math.max(maxDecorationHeight, image.getBounds().height); maxDecorationWidth = Math.max(maxDecorationWidth, image.getBounds().width); } } } }