/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* UIUtilities.java
* Created: Dec. 8 / 2003
* By: David Mosimann
*/
package org.openquark.util.ui;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.SystemColor;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.plaf.OptionPaneUI;
import javax.swing.plaf.basic.BasicBorders;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicOptionPaneUI;
import javax.swing.plaf.basic.BasicToggleButtonUI;
import javax.swing.text.JTextComponent;
import javax.swing.text.Keymap;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
/**
* A collection of user interfaces helper methods.
*/
public class UIUtilities {
/** An action property for specifying whether a regualar or toggle button should be created. */
public static final String TOGGLE_BUTTON = "TOGGLE_BUTTON"; //$NON-NLS-1$
/** Rendering hints - render at highest quality*/
private static final RenderingHints RENDERING_HINTS_HIGH_QUALITY = new RenderingHints(null);
static {
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
RENDERING_HINTS_HIGH_QUALITY.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
/** Enumeration indicating image flip orientation */
public static final class FlipOrientation {
/** Vertical Flip */
public static final FlipOrientation Vertical = new FlipOrientation("Vertical Flip"); //$NON-NLS-1$
/** Horizontal Flip */
public static final FlipOrientation Horizontal = new FlipOrientation("Horizontal Flip"); //$NON-NLS-1$
/** Vertical and Horizontal Flip */
public static final FlipOrientation BiDirectional = new FlipOrientation("Vertical and Horizontal Flip"); //$NON-NLS-1$
private final String enumType;
private FlipOrientation(String type) {
if (type == null) {
throw new NullPointerException();
}
enumType = type;
}
@Override
public String toString() {
return enumType;
}
}
/**
* This class should never be constructed. It's only purpose is to collect useful static methods
* similar to how the SwingUtilities class works.
*/
private UIUtilities() {
super();
}
/**
* Creates a new JButton with the flat appearance. It uses the same rollover effect as flat buttons
* in a toolbar.
* @return a JButton with the roll over property set and the border customized to show the rollover effect
*/
public static JButton CreateFlatButton() {
JButton button = new JButton();
makeButtonFlat(button);
return button;
}
/**
* Creates a new JToggleButton with the flat appearance.
* It uses the same rollover effect as flat buttons in a toolbar.
* @return a JButton with the roll over property set and the border customized to show the rollover effect
*/
public static JToggleButton CreateFlatToggleButton() {
JToggleButton button = new JToggleButton();
makeButtonFlat(button);
return button;
}
/**
* Creates a new JButton with the flat appearance.
* It uses the same rollover effect as flat buttons in a toolbar.
* The TOGGLE_BUTTON boolean property is checked to determine whether to create a toggle
* button or a regular one (default).
* @param action the action to be hooked up to the button
* @return a JButton with the roll over property set and the border customized to show the rollover effect
*/
public static AbstractButton CreateFlatButton(Action action) {
// Create the button
boolean toggleButton = false;
if (action != null) {
Object toggleButtonObj = action.getValue(TOGGLE_BUTTON);
toggleButton = (toggleButtonObj instanceof Boolean) ? ((Boolean) toggleButtonObj).booleanValue() : false;
}
AbstractButton button = toggleButton?(AbstractButton)CreateFlatToggleButton():CreateFlatButton();
if (action != null) {
button.setAction(action);
}
return button;
}
public static void makeButtonFlat(AbstractButton button) {
// Override the default look and feel: use basic L&F because some L&F (esp. WinXP)
// ignores the border property
if(button instanceof JToggleButton) {
button.setUI(new BasicToggleButtonUI());
} else {
button.setUI(new BasicButtonUI());
}
button.setRolloverEnabled(true);
UIDefaults table = UIManager.getLookAndFeelDefaults();
button.setBorder(new BasicBorders.RolloverButtonBorder(
table.getColor("controlShadow"), //$NON-NLS-1$
table.getColor("controlDkShadow"), //$NON-NLS-1$
table.getColor("controlHighlight"), //$NON-NLS-1$
table.getColor("controlLtHighlight"))); //$NON-NLS-1$
}
/**
* A helper class for creating actions for a toggle button.
*/
public static abstract class AbstractToggleAction extends AbstractAction {
/**
* AbstractToggleAction constructor.
*/
public AbstractToggleAction(String name, Icon icon) {
super(name, icon);
putValue(TOGGLE_BUTTON, Boolean.TRUE);
}
}
/**
* Shifts the image to the specified coordinates, growing or
* shrinking the image size as required.
*
* @param originalImage
* @param x horizontal position of top left corner
* @param y vertical position of top left corner
* @return image containing the original at the specified position
*/
public static Image shiftImage(Image originalImage, int x, int y) {
// Create a blank image and initialize graphics painter
BufferedImage newImage = new BufferedImage(
originalImage.getWidth(null) + x,
originalImage.getHeight(null) + y,
BufferedImage.TYPE_INT_ARGB_PRE
);
Graphics2D g2d = newImage.createGraphics();
g2d.setRenderingHints(RENDERING_HINTS_HIGH_QUALITY);
// Now paint the original on the new image
g2d.drawImage(originalImage, x, y, null);
g2d.dispose();
return newImage;
}
/**
* Crops the edges of the image, as specified. If the crop dimensions
* are negative, the image is grown.
*
* @param originalImage
* @param left number of pixels to trim from the the left edge
* @param top pixels to trim from the top edge
* @param right pixels to trim from the right edge
* @param bottom pixels to trim from the bottom edge
* @return cropped image
*/
public static Image cropImage(Image originalImage, int left, int top, int right, int bottom) {
BufferedImage newImage = new BufferedImage(
originalImage.getWidth(null) - left - right,
originalImage.getHeight(null) - top - bottom,
BufferedImage.TYPE_INT_ARGB_PRE
);
Graphics2D g2d = newImage.createGraphics();
g2d.setRenderingHints(RENDERING_HINTS_HIGH_QUALITY);
g2d.drawImage(originalImage, -1 * left, -1 * top, null);
g2d.dispose();
return newImage;
}
/**
* Rotates the image around its center by the specified angle. The original image
* size is maintained, so cropping may occur as a result of the rotation.
*
* @param originalImage
* @param theta angle in radians (a positive angle indicates clockwise rotation)
* @return rotated image
*/
public static Image rotateImage (Image originalImage, double theta) {
BufferedImage newImage = new BufferedImage(
originalImage.getWidth(null),
originalImage.getHeight(null),
BufferedImage.TYPE_INT_ARGB_PRE
);
Graphics2D g2d = newImage.createGraphics();
g2d.setRenderingHints(RENDERING_HINTS_HIGH_QUALITY);
g2d.rotate(theta, originalImage.getWidth(null) / (double)2, originalImage.getHeight(null) / (double)2);
g2d.drawImage( originalImage, 0, 0, null);
g2d.dispose();
return newImage;
}
/**
* Flips the image vertically and/or horizontally.
*
* @param originalImage
* @param flipType flip direction
* @return flipped image
*/
public static Image flipImage (Image originalImage, FlipOrientation flipType) {
BufferedImage newImage = new BufferedImage(
originalImage.getWidth(null),
originalImage.getHeight(null),
BufferedImage.TYPE_INT_ARGB_PRE
);
Graphics2D g2d = newImage.createGraphics();
g2d.setRenderingHints(RENDERING_HINTS_HIGH_QUALITY);
AffineTransform flipTransform = new AffineTransform(
(flipType == FlipOrientation.Horizontal || flipType == FlipOrientation.BiDirectional)? -1.0 : 1.0,
0.0, 0.0,
(flipType == FlipOrientation.Vertical || flipType == FlipOrientation.BiDirectional)? -1.0 : 1.0,
0.0, 0.0);
flipTransform.translate(
(flipType == FlipOrientation.Horizontal || flipType == FlipOrientation.BiDirectional)? -originalImage.getWidth(null) : 0.0,
(flipType == FlipOrientation.Vertical || flipType == FlipOrientation.BiDirectional)? -originalImage.getHeight(null) : 0.0);
g2d.setTransform(flipTransform);
g2d.drawImage(originalImage, 0, 0, null);
g2d.dispose();
return newImage;
}
// Helper fields for fixMenuItem()
private static final String lowerCaseOSName = System.getProperty("os.name").toLowerCase();
private static final boolean JUSTIFY_MENU_ITEM_HACK =
System.getProperty("java.version").startsWith("1.5") &&
!(lowerCaseOSName.startsWith("mac os x") || lowerCaseOSName.endsWith("vista"));
/**
* Fix up the given menu item so that it is justified correctly, has the associated icon, has no tooltip.
* @param menuItem the menu item to fix.
* @return the menu item that was fixed. ie. the menuItem param.
*/
public static JMenuItem fixMenuItem(JMenuItem menuItem) {
// HACK: Workaround for left-justifying icons. Sun Bug ID's: 4199382, 4203899.
// Hack seems to bugger up mac os x
// On Vista it makes the icon shift left enough so that you can't see most of it.
// Fixed in Java 6.
if (JUSTIFY_MENU_ITEM_HACK) {
// Get the icon, calculate its width.
Icon buttonIcon = menuItem.getIcon() != null ? menuItem.getIcon() :
menuItem.getAction() != null ? (Icon) menuItem.getAction().getValue(Action.SMALL_ICON) : null;
int iconWidth = (buttonIcon == null) ? -(menuItem.getIconTextGap()) : buttonIcon.getIconWidth();
Insets insets = menuItem.getInsets();
insets.left -= iconWidth;
menuItem.setMargin(insets);
}
// Menu items should not have tooltips, so clear it in case the action specifies one
menuItem.setToolTipText(null);
return menuItem;
}
/**
* Creates a new JMenuItem and configures it for use in a popup menu.
* @param action Action - the action used to configure the JMenuItem
* @return JMenuItem a new menu item for the action.
*/
public static JMenuItem makeNewMenuItem(Action action) {
JMenuItem newMenuItem = new JMenuItem(action);
return fixMenuItem(newMenuItem);
}
/**
* A helper function to paint a watermark for a component.
* This should be called in the paintComponent method before calling the super class method.
* @param g
*/
public static void paintWithWatermarkHelper(JComponent component, ImageIcon watermark, Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Paint oldPaint = g2.getPaint();
g2.setPaint(component.getBackground());
try {
// Fill in the background of the component.
g2.fillRect(0, 0, component.getWidth(), component.getHeight());
// Draw the background image, if any.
if (watermark != null) {
// draw the image centred in the visible area, and scaled to fit
Rectangle viewRect = new Rectangle (0, 0, component.getWidth(), component.getHeight());
Component parent = component.getParent();
if (parent instanceof JViewport) {
JViewport viewport = (JViewport) parent;
viewRect = viewport.getViewRect();
}
int imageWidth = watermark.getIconWidth();
int imageHeight = watermark.getIconHeight();
double xZoom = viewRect.getWidth() / imageWidth;
double yZoom = viewRect.getHeight() / imageHeight;
double zoom = Math.min (xZoom, yZoom);
int drawnWidth = (int)(imageWidth * zoom);
int drawnHeight = (int)(imageHeight * zoom);
int x = viewRect.x + (viewRect.width - drawnWidth) / 2;
int y = viewRect.y + (viewRect.height - drawnHeight) / 2;
Composite oldComposite = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f));
g2.drawImage(watermark.getImage(), x, y, x + drawnWidth, y + drawnHeight, 0, 0, imageWidth, imageHeight, null);
g2.setComposite(oldComposite);
}
}
finally {
g2.setPaint(oldPaint);
}
}
/**
* Returns the parent component of the component c that has the given type,
* or <code>null</code> if such parent does not exist.
* @param c
* @param type
* @return Component
*/
public static Component getParent(Component c, Class<? extends Container> type) {
c = c.getParent();
while (c != null) {
// assume that they are loaded by the same classloader
if (c.getClass() == type) {
return c;
}
c = c.getParent();
}
return null;
}
/**
* A helper method for setting the bold font attribute in the given component.
* @param c
* @param useBold
*/
public static void setFontBold(Component c, boolean useBold) {
Font f = c.getFont ();
int style = f.getStyle();
if (useBold) {
style |= Font.BOLD;
} else {
style &= ~Font.BOLD;
}
c.setFont(f.deriveFont(style));
}
/**
* A helper method for setting the italic font attribute in the given component.
* @param c
* @param useItalic
*/
public static void setFontItalic(Component c, boolean useItalic) {
Font f = c.getFont ();
int style = f.getStyle();
if (useItalic) {
style |= Font.ITALIC;
} else {
style &= ~Font.ITALIC;
}
c.setFont(f.deriveFont(style));
}
/**
* Brightens each of the RGB components of color by the specified factor.
* Note: This is identical to the java.awt.Color.brighten() method, using a variable factor.
*
* @param color color to brighten
* @param factor luminosity factor; if negative, the color is darkened
* @return brightened color
*/
public static Color brightenColor(Color color, double factor) {
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
int i = (int) (1.0 / (1.0 - factor));
if ( r == 0 && g == 0 && b == 0) {
return new Color(i, i, i);
}
if ( r > 0 && r < i ) {
r = i;
}
if ( g > 0 && g < i ) {
g = i;
}
if ( b > 0 && b < i ) {
b = i;
}
return new Color(Math.min((int)(r/factor), 255),
Math.min((int)(g/factor), 255),
Math.min((int)(b/factor), 255));
}
/**
* Returns an icon that combines the 2 specified icons.
* One will be drawn over top of the base icon.
* The resulting icon will be large enough to hold both icons.
* @param underIcon the icon to be drawn first
* @param overIcon the icon to be drawn over top
* @return the combined icon
*/
public static Icon combineIcons(Icon underIcon, Icon overIcon) {
int newWidth = Math.max(underIcon.getIconWidth(), overIcon.getIconWidth());
int newHeight = Math.max(underIcon.getIconHeight(), overIcon.getIconHeight());
BufferedImage combinedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = combinedImage.createGraphics();
underIcon.paintIcon(null, g2d, 0, 0);
overIcon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return new ImageIcon(combinedImage);
}
/**
* Changes the specified text component to support undo and redo using Ctrl-Z and Ctrl-Y.
* @param textComponent the text component to be modified
*/
public static void makeTextComponentUndoable(JTextComponent textComponent) {
final UndoManager undoManager = new UndoManager();
final Action undoAction = new AbstractAction(UIMessages.instance.getString("GenericUndoName")) { //$NON-NLS-1$
private static final long serialVersionUID = -2135822508998640523L;
public void actionPerformed(ActionEvent e) {
try {
if (undoManager.canUndo()) {
undoManager.undo();
}
}
catch (CannotUndoException ex) {
}
}
};
final Action redoAction = new AbstractAction(UIMessages.instance.getString("GenericRedoName")) { //$NON-NLS-1$
private static final long serialVersionUID = 2928127985356997903L;
public void actionPerformed(ActionEvent e) {
try {
if (undoManager.canRedo()) {
undoManager.redo();
}
}
catch (CannotUndoException ex) {
}
}
};
UndoableEditListener undoListener = new UndoableEditListener() {
public void undoableEditHappened(UndoableEditEvent e) {
undoManager.addEdit(e.getEdit());
}
};
textComponent.getDocument().addUndoableEditListener(undoListener);
Keymap keymap = JTextComponent.addKeymap("TextUndoRedoKeymap", textComponent.getKeymap()); //$NON-NLS-1$
keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK), undoAction);
keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK), redoAction);
textComponent.setKeymap(keymap);
}
/**
* Loads an <code>Icon</code> from the specified icon path. The <code>ClassLoader</code>
* of the given class will be used to load the icon.
* @param iconUrl
* @return Icon
*/
public static Icon LoadImageIcon(URL iconUrl) {
if (iconUrl != null) {
return new ImageIcon(iconUrl);
}
return null;
}
/**
* Loads an <code>Icon</code> from the specified icon path. This method will use
* the <code>ClassLoader</code> that loaded this class to load the icon.
* @param iconPath
* @return Icon
*/
public static Icon LoadImageIcon(String iconPath) {
return LoadImageIcon(UIUtilities.class, iconPath);
}
/**
* Loads an <code>Icon</code> from the specified icon path. This method will use
* the <code>ClassLoader</code> that loaded this class to load the icon.
* @param c the class to get the resource from / for
* @param iconPath
* @return Icon
*/
public static Icon LoadImageIcon(Class<?> c, String iconPath) {
if (iconPath != null && c != null) {
URL imagePath = c.getResource(iconPath);
return LoadImageIcon(imagePath);
}
return null;
}
/**
* Method makeLocalObjectDataFlavor
*
* @param representationClass
* @param name
*
* @return Returns a DataFlavour that represents a Java object local to this VM
*/
public static DataFlavor makeLocalObjectDataFlavor (Class<?> representationClass, String name) {
return new DataFlavor (DataFlavor.javaJVMLocalObjectMimeType + ";class=" + representationClass.getName(), name); //$NON-NLS-1$
}
/**
* Create a label that looks a bit like a post-it note, nice for giving
* feedback without makeing people think they've made an error.
* @param text
* @return JLabel
*/
public static JLabel createInfoLabel(String text) {
JLabel label = new JLabel(text);
label.setOpaque(true);
Border inner = BorderFactory.createEmptyBorder(2,4,2,4);
Border outer = BorderFactory.createLineBorder(SystemColor.info.darker());
label.setBorder(BorderFactory.createCompoundBorder(outer, inner));
label.setBackground(SystemColor.info);
return label;
}
/**
* Add a search box to a UtilTree.
* @param tree A searchable UtilTree.
* @return A panel containing the given UtilTree and a search box.
*/
public static JPanel makeSearchablePanel(UtilTree tree) {
JPanel panel = new JPanel(new BorderLayout());
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(tree);
panel.add(scrollPane, BorderLayout.CENTER);
SearchTextField searchField = new SearchTextField(tree);
panel.add(searchField, BorderLayout.SOUTH);
return panel;
}
/**
* Used by getJOptionPaneIcon().
* Cache from message type (JOptionPane int constant representing message type)
* to icon representing that message type.
*/
private static final Map<Integer, Icon> jOptionPaneMessageTypeToIconMap = new HashMap<Integer, Icon>();
/**
* Get the icon used in the JOptionPane to signify its message type.
* Note that this is almost the same as a call to something like: UIManager.getIcon("OptionPane.questionIcon")
* but that doesn't work on GTK look-and-feel since there is no corresponding entry in its laf defaults map.
*
* @param jOptionPaneMessageType One of the message types constants defined in the javax.swing.JOptionPane class.
* @return the corresponding icon, or null if the icon is undefined for the provided message type.
*/
public static Icon getJOptionPaneIcon(int jOptionPaneMessageType) {
/*
* HACK - workaround for GTK.
* We create a new JOptionPane, get its UI (which should be a BasicOptionPaneUI), then call BasicOptionPaneUI.getIconForType().
* GTK uses SynthOptionPaneUI (which is package protected), which eventually defers to SynthDefaultLookup to look
* up default values for ui items such as icons.
* However using this with non-Synth UIs causes lookup to defer to the basic (non-synth) lookup scheme.
* Since we can't instantiate SynthOptionPaneUI (which is the SynthUI that we want) we are stuck calling the protected
* method getIconForType() reflectively after unprotecting it.
*/
Integer messageTypeInteger = new Integer(jOptionPaneMessageType);
Icon icon = jOptionPaneMessageTypeToIconMap.get(messageTypeInteger);
if (icon == null) {
// Get the icon from a new JOptionPane's UI.
OptionPaneUI ui = (new JOptionPane()).getUI();
// The code below only works for BasicOptionPaneUIs.
if (!(ui instanceof BasicOptionPaneUI)) {
ui = new BasicOptionPaneUI();
// Have to use a UI with a JOptionPane for it to initialize its icons.
JOptionPane optionPane = new JOptionPane();
optionPane.setUI(ui);
}
BasicOptionPaneUI optionPaneUI = (BasicOptionPaneUI)ui;
try {
Method method = BasicOptionPaneUI.class.getDeclaredMethod("getIconForType", new Class[] {int.class}); //$NON-NLS-1$
boolean oldAccessible = method.isAccessible();
method.setAccessible(true);
try {
icon = (Icon)method.invoke(optionPaneUI, new Object[] {new Integer(jOptionPaneMessageType)});
} finally {
method.setAccessible(oldAccessible);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
jOptionPaneMessageTypeToIconMap.put(messageTypeInteger, icon);
}
return icon;
}
}