package net.sourceforge.tuned.ui; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.RadialGradientPaint; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RectangularShape; import javax.swing.border.AbstractBorder; public class ShadowBorder extends AbstractBorder { private int smoothness; private int smoothnessOffset; private int offset; public ShadowBorder() { this(2, 2, 12); } public ShadowBorder(int offset, int smoothness, int smoothnessOffset) { this.offset = offset; this.smoothness = smoothness; this.smoothnessOffset = smoothnessOffset; } @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Graphics2D g2d = (Graphics2D) g; Color bg = new Color(0, 0, 0, 81); Color faded = new Color(0, 0, 0, 0); int a = smoothness + smoothnessOffset; Rectangle2D main = new Rectangle2D.Double(a, a, width - a * 2, height - a * 2); g2d.setPaint(bg); g2d.fill(main); Rectangle2D right = new Rectangle2D.Double(main.getMaxX(), a, a, main.getHeight()); Rectangle2D left = new Rectangle2D.Double(0, a, a, main.getHeight()); Rectangle2D top = new Rectangle2D.Double(a, 0, main.getWidth(), a); Rectangle2D bottom = new Rectangle2D.Double(a, main.getMaxY(), main.getWidth(), a); g2d.setPaint(GradientStyle.LEFT_TO_RIGHT.getGradientPaint(right, bg, faded)); g2d.fill(right); g2d.setPaint(GradientStyle.RIGHT_TO_LEFT.getGradientPaint(left, bg, faded)); g2d.fill(left); g2d.setPaint(GradientStyle.BOTTOM_TO_TOP.getGradientPaint(top, bg, faded)); g2d.fill(top); g2d.setPaint(GradientStyle.TOP_TO_BOTTOM.getGradientPaint(bottom, bg, faded)); g2d.fill(bottom); Rectangle2D topLeftCorner = new Rectangle2D.Double(0, 0, a, a); Rectangle2D topRightCorner = new Rectangle2D.Double(width - a, 0, a, a); Rectangle2D bottomLeftCorner = new Rectangle2D.Double(0, height - a, a, a); Rectangle2D bottomRightCorner = new Rectangle2D.Double(width - a, height - a, a, a); g2d.setPaint(CornerGradientStyle.TOP_LEFT.getGradientPaint(topLeftCorner, a, bg, faded)); g2d.fill(topLeftCorner); g2d.setPaint(CornerGradientStyle.TOP_RIGHT.getGradientPaint(topRightCorner, a, bg, faded)); g2d.fill(topRightCorner); g2d.setPaint(CornerGradientStyle.BOTTOM_LEFT.getGradientPaint(bottomLeftCorner, a, bg, faded)); g2d.fill(bottomLeftCorner); g2d.setPaint(CornerGradientStyle.BOTTOM_RIGHT.getGradientPaint(bottomRightCorner, a, bg, faded)); g2d.fill(bottomRightCorner); } @Override public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0, 0, 0, 0)); } @Override public Insets getBorderInsets(Component c, Insets insets) { insets.top = insets.left = Math.max(smoothness - offset, 4); insets.bottom = insets.right = Math.max(smoothness + offset, 4); return insets; } private static enum CornerGradientStyle { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT; public RadialGradientPaint getGradientPaint(RectangularShape shape, float radius, Color gradientBeginColor, Color gradientEndColor) { Point2D center = null; switch (this) { case TOP_LEFT: center = new Point2D.Double(shape.getX() + radius, shape.getY() + radius); break; case TOP_RIGHT: center = new Point2D.Double(shape.getX() + 0, shape.getY() + radius); break; case BOTTOM_LEFT: center = new Point2D.Double(shape.getX() + radius, shape.getY() + 0); break; case BOTTOM_RIGHT: center = new Point2D.Double(shape.getX() + 0, shape.getY() + 0); break; default: return null; } float[] dist = { 0.0f, 1.0f }; Color[] colors = { gradientBeginColor, gradientEndColor }; return new RadialGradientPaint(center, radius, dist, colors); } } }