Shadow Border
28/01/2009
/* * Created on 17 oct. 06 * By Gabriel DROMARD */ import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.RenderingHints; import javax.swing.JPanel; import javax.swing.border.AbstractBorder; /** * A class which implements a shadow border. * * <p>Code Example: </p> * <pre> * JPanel root = new JPanel(); * // Generate 4 example for each TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT and BOTTOM_RIGHT configurations * for(int i=0; i<4; ++i) { * JPanel test = new JPanel(); * test.setPreferredSize(new Dimension(100, 100)); * test.setBackground(Color.WHITE); * test.setOpaque(false); * test.setBorder(new ShadowBorder(Color.GRAY, Color.GRAY, 10, i)); * root.add(test); * } * //SwingHelper.openInFrame(root); * JFrame frame = new JFrame(); * frame.getContentPane().setLayout(new BorderLayout()); * frame.getContentPane().add(root, BorderLayout.CENTER); * frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); * frame.pack(); * frame.setVisible(true); * </pre> */ public class ShadowBorder extends AbstractBorder { private int shadowWidth = 10; private int inset = 5; protected Color lineBorderColor = null; protected Color shadowColor = null; protected int type = 2; public static final int TOP_LEFT = 0; public static final int TOP_RIGHT = 1; public static final int BOTTOM_LEFT = 2; public static final int BOTTOM_RIGHT = 3; /** * Auto-generated main method to display this * JPanel inside a new JFrame. */ public static void main(String[] args) { JPanel root = new JPanel(); for(int i=0; i<4; ++i) { JPanel test = new JPanel(); test.setPreferredSize(new Dimension(100, 100)); test.setBackground(Color.WHITE); test.setOpaque(false); test.setBorder(new ShadowBorder(Color.GRAY, Color.GRAY, 10, i)); root.add(test); } SwingHelper.openInFrame(root); } /** * Creates a shadow border with the specified shadow width and whose * colors will be derived from the background color of the * component passed into the paintBorder method. * @param shadowWidth the length of shadow * @param * @param * @param */ public ShadowBorder(Color shadowColor, Color lineBorderColor, int shadowWidth, int type) { super(); this.shadowWidth = shadowWidth; this.shadowColor = shadowColor; this.lineBorderColor = lineBorderColor; this.type = type; } /** * Returns the insets of the border. * @param c the component for which this border insets value applies */ public Insets getBorderInsets(Component c) { int hPosition = shadowWidth; int vPosition = shadowWidth; if(type == TOP_LEFT) { hPosition = 0; vPosition = 0; } else if(type == TOP_RIGHT) { hPosition = shadowWidth; vPosition = 0; } else if(type == BOTTOM_LEFT) { hPosition = 0; vPosition = shadowWidth; } else if(type == BOTTOM_RIGHT) { hPosition = shadowWidth; vPosition = shadowWidth; } return new Insets((shadowWidth - hPosition)+inset, (shadowWidth - vPosition)+inset, hPosition+inset, vPosition+inset); } /** * Reinitialize the insets parameter with this Border's current Insets. * @param c the component for which this border insets value applies * @param insets the object to be reinitialized */ public Insets getBorderInsets(Component c, Insets insets) { insets.left = insets.top = insets.right = insets.bottom = shadowWidth+2; return insets; } /** * Returns the shadow color of the border * when rendered on the specified component. If no shadow * color was specified at instantiation, the shadow color * is derived from the specified component's background color. * @param c the component for which the shadow may be derived */ public Color getShadowColor(Component c) { Color shadow = getShadowColor(); if(shadow == null) shadow = c.getBackground().darker().darker(); return shadow; } /** * Returns the shadow color of the border. * Will return null if no shadow color was specified at instantiation. */ public Color getShadowColor() { return shadowColor; } /** * Returns whether or not the border is opaque. */ public boolean isBorderOpaque() { return true; } /** * Paints the border for the specified component with the specified position and size. * @param c the component for which this border is being painted * @param g the paint graphics * @param x the x position of the painted border * @param y the y position of the painted border * @param width the width of the painted border * @param height the height of the painted border */ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { int hPosition = shadowWidth; int vPosition = shadowWidth; if(type == TOP_LEFT) { hPosition = 0; vPosition = 0; } else if(type == TOP_RIGHT) { hPosition = shadowWidth; vPosition = 0; } else if(type == BOTTOM_LEFT) { hPosition = 0; vPosition = shadowWidth; } else if(type == BOTTOM_RIGHT) { hPosition = shadowWidth; vPosition = shadowWidth; } width = width - 1; height = height - 1; Graphics2D gg = (Graphics2D) g; // backup old color to be able to restore it at the end of paint Color oldColor = gg.getColor(); // Translate position gg.translate(x, y); // paint shadow paintShadow(c, gg, getShadowColor(c), hPosition, vPosition, width-shadowWidth, height-shadowWidth, shadowWidth); // Fill with background color the panel gg.setColor(c.getBackground()); gg.fillRect(shadowWidth - hPosition, shadowWidth - vPosition, width-shadowWidth, height-shadowWidth); // Draw line border if (lineBorderColor != null) { gg.setColor(lineBorderColor); gg.drawRect(shadowWidth - hPosition, shadowWidth - vPosition, width-shadowWidth, height-shadowWidth); } // Reset position gg.translate(-x, -y); // Re put oldColor gg.setColor(oldColor); } /** * * @param c the component for which this border is being painted * @param gg the paint graphics * @param shadowColor The color of the shadow * @param x the x position of the painted border * @param y the y position of the painted border * @param width the width of the painted border * @param height the height of the painted border * @param shadowWidth The shadow width */ public static void paintShadow(Component c, Graphics2D gg, Color shadowColor, int x, int y, int width, int height, int shadowWidth) { // Set anti aliasing gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING , RenderingHints.VALUE_ANTIALIAS_ON); // Draw shadow AlphaComposite ac = null; gg.setColor(shadowColor); // Initial shadow width: int sw = width - 2*shadowWidth; // Initial shadow height: int sh = height - 2*shadowWidth; // Draw shadow for(int i=0; i<shadowWidth; ++i) { ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f/(i+1)); gg.setComposite(ac); gg.fillRoundRect(x+shadowWidth-i, y+shadowWidth-i, sw + 2*i, sh + 2*i, i*2, i*2); } // Reset transparency ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1); gg.setComposite(ac); } }