/* * Copyright (c) 2001-2013 JGoodies Software GmbH. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o 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. * * o Neither the name of JGoodies Software GmbH 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. */ package org.pushingpixels.substance.internal.contrib.jgoodies.looks.common; import java.awt.Component; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.border.AbstractBorder; /** * A border with a drop shadow intended to be used as the outer border * of popups. Can paint the screen background if used with heavy-weight * popup windows. * * @author Karsten Lentzsch * @version $Revision: 1.9 $ * * @see ShadowPopup * @see ShadowPopupFactory */ final class ShadowPopupBorder extends AbstractBorder { /** * The drop shadow needs 5 pixels at the bottom and the right hand side. */ private static final int SHADOW_SIZE = 5; /** * The singleton instance used to draw all borders. */ private static ShadowPopupBorder instance = new ShadowPopupBorder(); /** * The drop shadow is created from a PNG image with 8 bit alpha channel. */ private static Image shadow = new ImageIcon(ShadowPopupBorder.class.getResource("shadow.png")).getImage(); // Instance Creation ***************************************************** /** * Returns the singleton instance used to draw all borders. */ public static ShadowPopupBorder getInstance() { return instance; } /** * Paints the border for the specified component with the specified * position and size. */ @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { // fake drop shadow effect in case of heavy weight popups JComponent popup = (JComponent) c; Image hShadowBg = (Image) popup.getClientProperty(ShadowPopupFactory.PROP_HORIZONTAL_BACKGROUND); if (hShadowBg != null) { g.drawImage(hShadowBg, x, y + height - 5, c); } Image vShadowBg = (Image) popup.getClientProperty(ShadowPopupFactory.PROP_VERTICAL_BACKGROUND); if (vShadowBg != null) { g.drawImage(vShadowBg, x + width - 5, y, c); } // draw drop shadow g.drawImage(shadow, x + 5, y + height - 5, x + 10, y + height, 0, 6, 5, 11, null, c); g.drawImage(shadow, x + 10, y + height - 5, x + width - 5, y + height, 5, 6, 6, 11, null, c); g.drawImage(shadow, x + width - 5, y + 5, x + width, y + 10, 6, 0, 11, 5, null, c); g.drawImage(shadow, x + width - 5, y + 10, x + width, y + height - 5, 6, 5, 11, 6, null, c); g.drawImage(shadow, x + width - 5, y + height - 5, x + width, y + height, 6, 6, 11, 11, null, c); } /** * Returns the insets of the border. */ @Override public Insets getBorderInsets(Component c) { return new Insets(0, 0, SHADOW_SIZE, SHADOW_SIZE); } /** * Reinitializes 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 * @return the {@code insets} object */ @Override public Insets getBorderInsets(Component c, Insets insets) { insets.left = insets.top = 0; insets.right = insets.bottom = SHADOW_SIZE; return insets; } }