DropShadowBorder.java
上传用户:zhengdagz
上传日期:2014-03-06
资源大小:1956k
文件大小:15k
源码类别:

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: DropShadowBorder.java,v 1.10 2005/10/13 17:19:34 rbair Exp $
  3.  *
  4.  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
  5.  * Santa Clara, California 95054, U.S.A. All rights reserved.
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  * 
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.  */
  21. package org.jdesktop.swingx.border;
  22. import java.awt.Color;
  23. import java.awt.Component;
  24. import java.awt.Graphics;
  25. import java.awt.Graphics2D;
  26. import java.awt.Image;
  27. import java.awt.Insets;
  28. import java.awt.Point;
  29. import java.awt.Rectangle;
  30. import java.awt.RenderingHints;
  31. import java.awt.geom.RoundRectangle2D;
  32. import java.awt.image.BufferedImage;
  33. import java.awt.image.ConvolveOp;
  34. import java.awt.image.Kernel;
  35. import java.util.HashMap;
  36. import java.util.Map;
  37. import javax.swing.UIManager;
  38. import javax.swing.border.Border;
  39. /**
  40.  * Implements a DropShadow for components. In general, the DropShadowBorder will
  41.  * work with any rectangular components that do not have a default border installed
  42.  * as part of the look and feel, or otherwise. For example, DropShadowBorder works
  43.  * wonderfully with JPanel, but horribly with JComboBox.
  44.  *
  45.  * @author rbair
  46.  */
  47. public class DropShadowBorder implements Border {
  48.     private static enum Position {TOP, TOP_LEFT, LEFT, BOTTOM_LEFT,
  49.                     BOTTOM, BOTTOM_RIGHT, RIGHT, TOP_RIGHT};
  50.                     
  51.     private static final Map<Integer,Map<Position,BufferedImage>> CACHE 
  52.             = new HashMap<Integer,Map<Position,BufferedImage>>();
  53.                         
  54.     private Color lineColor;
  55.     private int lineWidth;
  56.     private int shadowSize;
  57.     private float shadowOpacity;
  58.     private int cornerSize;
  59.     private boolean showTopShadow;
  60.     private boolean showLeftShadow;
  61.     private boolean showBottomShadow;
  62.     private boolean showRightShadow;
  63.     
  64.     public DropShadowBorder() {
  65.         this(UIManager.getColor("Control"), 1, 5);
  66.     }
  67.     
  68.     public DropShadowBorder(Color lineColor, int lineWidth, int shadowSize) {
  69.         this(lineColor, lineWidth, shadowSize, .5f, 12, false, false, true, true);
  70.     }
  71.     
  72.     public DropShadowBorder(Color lineColor, int lineWidth, boolean showLeftShadow) {
  73.         this(lineColor, lineWidth, 5, .5f, 12, false, showLeftShadow, true, true);
  74.     }
  75.     
  76.     public DropShadowBorder(Color lineColor, int lineWidth, int shadowSize,
  77.             float shadowOpacity, int cornerSize, boolean showTopShadow,
  78.             boolean showLeftShadow, boolean showBottomShadow, boolean showRightShadow) {
  79.         this.lineColor = lineColor;
  80.         this.lineWidth = lineWidth;
  81.         this.shadowSize = shadowSize;
  82.         this.shadowOpacity = shadowOpacity;
  83.         this.cornerSize = cornerSize;
  84.         this.showTopShadow = showTopShadow;
  85.         this.showLeftShadow = showLeftShadow;
  86.         this.showBottomShadow = showBottomShadow;
  87.         this.showRightShadow = showRightShadow;
  88.     }
  89.     
  90.     /**
  91.      * @inheritDoc
  92.      */
  93.     public void paintBorder(Component c, Graphics graphics, int x, int y, int width, int height) {
  94.         /*
  95.          * 1) Get images for this border
  96.          * 2) Paint the images for each side of the border that should be painted
  97.          */
  98.         Map<Position,BufferedImage> images = getImages(null);
  99.         
  100.         //compute the edges of the component -- not including the border
  101.         Insets borderInsets = getBorderInsets(c);
  102.         int leftEdge = x + borderInsets.left - lineWidth;
  103.         int rightEdge = x + width - borderInsets.right;
  104.         int topEdge = y + borderInsets.top - lineWidth;
  105.         int bottomEdge = y + height - borderInsets.bottom;
  106.         Graphics2D g2 = (Graphics2D)graphics;
  107.         g2.setColor(lineColor);
  108.         
  109.         //The location and size of the shadows depends on which shadows are being
  110.         //drawn. For instance, if the left & bottom shadows are being drawn, then
  111.         //the left shadow extends all the way down to the corner, a corner is drawn,
  112.         //and then the bottom shadow begins at the corner. If, however, only the
  113.         //bottom shadow is drawn, then the bottom-left corner is drawn to the
  114.         //right of the corner, and the bottom shadow is somewhat shorter than before.
  115.         
  116.         Point topLeftShadowPoint = null;
  117.         if (showLeftShadow || showTopShadow) {
  118.             topLeftShadowPoint = new Point();
  119.             if (showLeftShadow && !showTopShadow) {
  120.                 topLeftShadowPoint.setLocation(x, y + shadowSize);
  121.             } else if (showLeftShadow && showTopShadow) {
  122.                 topLeftShadowPoint.setLocation(x, y);
  123.             } else if (!showLeftShadow && showTopShadow) {
  124.                 topLeftShadowPoint.setLocation(x + shadowSize, y);
  125.             }
  126.         }
  127.   
  128.         Point bottomLeftShadowPoint = null;
  129.         if (showLeftShadow || showBottomShadow) {
  130.             bottomLeftShadowPoint = new Point();
  131.             if (showLeftShadow && !showBottomShadow) {
  132.                 bottomLeftShadowPoint.setLocation(x, y + height - shadowSize - shadowSize);
  133.             } else if (showLeftShadow && showBottomShadow) {
  134.                 bottomLeftShadowPoint.setLocation(x, y + height - shadowSize);
  135.             } else if (!showLeftShadow && showBottomShadow) {
  136.                 bottomLeftShadowPoint.setLocation(x + shadowSize, y + height - shadowSize);
  137.             }
  138.         }
  139.         
  140.         Point bottomRightShadowPoint = null;
  141.         if (showRightShadow || showBottomShadow) {
  142.             bottomRightShadowPoint = new Point();
  143.             if (showRightShadow && !showBottomShadow) {
  144.                 bottomRightShadowPoint.setLocation(x + width - shadowSize, y + height - shadowSize - shadowSize);
  145.             } else if (showRightShadow && showBottomShadow) {
  146.                 bottomRightShadowPoint.setLocation(x + width - shadowSize, y + height - shadowSize);
  147.             } else if (!showRightShadow && showBottomShadow) {
  148.                 bottomRightShadowPoint.setLocation(x + width - shadowSize - shadowSize, y + height - shadowSize);
  149.             }
  150.         }
  151.         
  152.         Point topRightShadowPoint = null;
  153.         if (showRightShadow || showTopShadow) {
  154.             topRightShadowPoint = new Point();
  155.             if (showRightShadow && !showTopShadow) {
  156.                 topRightShadowPoint.setLocation(x + width - shadowSize, y + shadowSize);
  157.             } else if (showRightShadow && showTopShadow) {
  158.                 topRightShadowPoint.setLocation(x + width - shadowSize, y);
  159.             } else if (!showRightShadow && showTopShadow) {
  160.                 topRightShadowPoint.setLocation(x + width - shadowSize - shadowSize, y);
  161.             }
  162.         }
  163.         
  164.         if (showLeftShadow) {
  165.             Rectangle leftShadowRect = new Rectangle(x, (int)(topLeftShadowPoint.getY() + shadowSize), shadowSize, (int)(bottomLeftShadowPoint.getY() - topLeftShadowPoint.getY() - shadowSize));
  166.             g2.drawImage(images.get(Position.LEFT).getScaledInstance(leftShadowRect.width, leftShadowRect.height, Image.SCALE_FAST), leftShadowRect.x, leftShadowRect.y, null);
  167.         }
  168.         if (showBottomShadow) {
  169.             Rectangle bottomShadowRect = new Rectangle((int)(bottomLeftShadowPoint.getX() + shadowSize), y + height - shadowSize, (int)(bottomRightShadowPoint.getX() - bottomLeftShadowPoint.getX() - shadowSize), shadowSize);
  170.             g2.drawImage(images.get(Position.BOTTOM).getScaledInstance(bottomShadowRect.width, bottomShadowRect.height, Image.SCALE_FAST), bottomShadowRect.x, bottomShadowRect.y, null);
  171.         }
  172.         
  173.         if (showRightShadow) {
  174.             Rectangle rightShadowRect = new Rectangle(x + width - shadowSize, (int)(topRightShadowPoint.getY() + shadowSize), shadowSize, (int)(bottomRightShadowPoint.getY() - topRightShadowPoint.getY() - shadowSize));
  175.             g2.drawImage(images.get(Position.RIGHT).getScaledInstance(rightShadowRect.width, rightShadowRect.height, Image.SCALE_FAST), rightShadowRect.x, rightShadowRect.y, null);
  176.         }
  177.         
  178.         if (showTopShadow) {
  179.             Rectangle topShadowRect = new Rectangle((int)topLeftShadowPoint.getX() + shadowSize, y, (int)(topRightShadowPoint.getX() - topLeftShadowPoint.getX() - shadowSize), shadowSize);
  180.             g2.drawImage(images.get(Position.TOP).getScaledInstance(topShadowRect.width, topShadowRect.height, Image.SCALE_FAST), topShadowRect.x, topShadowRect.y, null);
  181.         }
  182.         
  183.         if (showLeftShadow || showTopShadow) {
  184.             g2.drawImage(images.get(Position.TOP_LEFT), null, (int)topLeftShadowPoint.getX(), (int)topLeftShadowPoint.getY());
  185.         }
  186.         if (showLeftShadow || showBottomShadow) {
  187.             g2.drawImage(images.get(Position.BOTTOM_LEFT), null, (int)bottomLeftShadowPoint.getX(), (int)bottomLeftShadowPoint.getY());
  188.         }
  189.         if (showRightShadow || showBottomShadow) {
  190.             g2.drawImage(images.get(Position.BOTTOM_RIGHT), null, (int)bottomRightShadowPoint.getX(), (int)bottomRightShadowPoint.getY());
  191.         }
  192.         if (showRightShadow || showTopShadow) {
  193.             g2.drawImage(images.get(Position.TOP_RIGHT), null, (int)topRightShadowPoint.getX(), (int)topRightShadowPoint.getY());
  194.         }
  195.     }
  196.     
  197.     private Map<Position,BufferedImage> getImages(Graphics2D g2) {
  198.         //first, check to see if an image for this size has already been rendered
  199.         //if so, use the cache. Else, draw and save
  200.         Map<Position,BufferedImage> images = CACHE.get(shadowSize);
  201.         if (images == null) {
  202.             images = new HashMap<Position,BufferedImage>();
  203.             /*
  204.              * Do draw a drop shadow, I have to:
  205.              *  1) Create a rounded rectangle
  206.              *  2) Create a BufferedImage to draw the rounded rect in
  207.              *  3) Translate the graphics for the image, so that the rectangle
  208.              *     is centered in the drawn space. The border around the rectangle
  209.              *     needs to be shadowWidth wide, so that there is space for the
  210.              *     shadow to be drawn.
  211.              *  4) Draw the rounded rect as black, with an opacity of 50%
  212.              *  5) Create the BLUR_KERNEL
  213.              *  6) Blur the image
  214.              *  7) copy off the corners, sides, etc into images to be used for
  215.              *     drawing the Border
  216.              */
  217.             int rectWidth = cornerSize + 1;
  218.             RoundRectangle2D rect = new RoundRectangle2D.Double(0, 0, rectWidth, rectWidth, cornerSize, cornerSize);
  219.             int imageWidth = rectWidth + shadowSize * 2;
  220.             BufferedImage image = new BufferedImage(imageWidth, imageWidth, BufferedImage.TYPE_INT_ARGB);
  221.             Graphics2D buffer = (Graphics2D)image.getGraphics();
  222.             buffer.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  223.             buffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  224.             buffer.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
  225.             buffer.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
  226.             buffer.setColor(new Color(0.0f, 0.0f, 0.0f, shadowOpacity));
  227.             buffer.translate(shadowSize, shadowSize);
  228.             buffer.fill(rect);
  229.             float blurry = 1.0f / (float)(shadowSize * shadowSize);
  230.             float[] blurKernel = new float[shadowSize * shadowSize];
  231.             for (int i=0; i<blurKernel.length; i++) {
  232.                 blurKernel[i] = blurry;
  233.             }
  234.             ConvolveOp blur = new ConvolveOp(new Kernel(shadowSize, shadowSize, blurKernel));
  235.             BufferedImage targetImage = new BufferedImage(imageWidth, imageWidth, BufferedImage.TYPE_INT_ARGB);
  236.             ((Graphics2D)targetImage.getGraphics()).drawImage(image, blur, -(shadowSize/2), -(shadowSize/2));
  237.             int x = 1;
  238.             int y = 1;
  239.             int w = shadowSize;
  240.             int h = shadowSize;
  241.             images.put(Position.TOP_LEFT, targetImage.getSubimage(x, y, w, h));
  242.             x = 1;
  243.             y = h;
  244.             w = shadowSize;
  245.             h = 1;
  246.             images.put(Position.LEFT, targetImage.getSubimage(x, y, w, h));
  247.             x = 1;
  248.             y = rectWidth;
  249.             w = shadowSize;
  250.             h = shadowSize;
  251.             images.put(Position.BOTTOM_LEFT, targetImage.getSubimage(x, y, w, h));
  252.             x = cornerSize + 1;
  253.             y = rectWidth;
  254.             w = 1;
  255.             h = shadowSize;
  256.             images.put(Position.BOTTOM, targetImage.getSubimage(x, y, w, h));
  257.             x = rectWidth;
  258.             y = x;
  259.             w = shadowSize;
  260.             h = shadowSize;
  261.             images.put(Position.BOTTOM_RIGHT, targetImage.getSubimage(x, y, w, h));
  262.             x = rectWidth;
  263.             y = cornerSize + 1;
  264.             w = shadowSize;
  265.             h = 1;
  266.             images.put(Position.RIGHT, targetImage.getSubimage(x, y, w, h));
  267.             x = rectWidth;
  268.             y = 1;
  269.             w = shadowSize;
  270.             h = shadowSize;
  271.             images.put(Position.TOP_RIGHT, targetImage.getSubimage(x, y, w, h));
  272.             x = shadowSize;
  273.             y = 1;
  274.             w = 1;
  275.             h = shadowSize;
  276.             images.put(Position.TOP, targetImage.getSubimage(x, y, w, h));
  277.                         
  278.             buffer.dispose();
  279.             image.flush();
  280.         }
  281.         return images;
  282.     }
  283.     
  284.     /**
  285.      * @inheritDoc
  286.      */
  287.     public Insets getBorderInsets(Component c) {
  288.         int top = showTopShadow ? lineWidth + shadowSize : lineWidth;
  289.         int left = showLeftShadow ? lineWidth + shadowSize : lineWidth;
  290.         int bottom = showBottomShadow ? lineWidth + shadowSize : lineWidth;
  291.         int right = showRightShadow ? lineWidth + shadowSize : lineWidth;
  292.         return new Insets(top, left, bottom, right);
  293.     }
  294.     
  295.     /**
  296.      * @inheritDoc
  297.      */
  298.     public boolean isBorderOpaque() {
  299.         return true;
  300.     }
  301.     
  302.     public boolean isShowTopShadow() {
  303.         return showTopShadow;
  304.     }
  305.     
  306.     public boolean isShowLeftShadow() {
  307.         return showLeftShadow;
  308.     }
  309.     
  310.     public boolean isShowRightShadow() {
  311.         return showRightShadow;
  312.     }
  313.     
  314.     public boolean isShowBottomShadow() {
  315.         return showBottomShadow;
  316.     }
  317.     
  318.     public int getLineWidth() {
  319.         return lineWidth;
  320.     }
  321.     
  322.     public Color getLineColor() {
  323.         return lineColor;
  324.     }
  325.     
  326.     public int getShadowSize() {
  327.         return shadowSize;
  328.     }
  329.     
  330.     public float getShadowOpacity() {
  331.         return shadowOpacity;
  332.     }
  333.     
  334.     public int getCornerSize() {
  335.         return cornerSize;
  336.     }
  337. }