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

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: JXPanel.java,v 1.14 2005/10/10 18:01:56 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;
  22. import java.awt.AlphaComposite;
  23. import java.awt.Color;
  24. import java.awt.Component;
  25. import java.awt.Composite;
  26. import java.awt.Dimension;
  27. import java.awt.GradientPaint;
  28. import java.awt.Graphics;
  29. import java.awt.Graphics2D;
  30. import java.awt.Insets;
  31. import java.awt.LayoutManager;
  32. import java.awt.Rectangle;
  33. import java.awt.image.BufferedImage;
  34. import javax.swing.JPanel;
  35. import javax.swing.RepaintManager;
  36. import javax.swing.Scrollable;
  37. /**
  38.  * A simple JPanel extension that adds translucency support.
  39.  * This component and all of its content will be displayed with the specified
  40.  * "alpha" transluscency property value.
  41.  *
  42.  * @author rbair
  43.  */
  44. public class JXPanel extends JPanel implements Scrollable {
  45.     private boolean scrollableTracksViewportHeight;
  46.     private boolean scrollableTracksViewportWidth;
  47.     
  48.     /**
  49.      * The alpha level for this component.
  50.      */
  51.     private float alpha = 1.0f;
  52.     /**
  53.      * If the old alpha value was 1.0, I keep track of the opaque setting because
  54.      * a translucent component is not opaque, but I want to be able to restore
  55.      * opacity to its default setting if the alpha is 1.0. Honestly, I don't know
  56.      * if this is necessary or not, but it sounded good on paper :)
  57.      * <p>TODO: Check whether this variable is necessary or not</p>
  58.      */
  59.     private boolean oldOpaque;
  60.     /**
  61.      * Indicates whether this component should inherit its parent alpha value
  62.      */
  63.     private boolean inheritAlpha = true;
  64.     /**
  65.      * Indicates whether the JXPanel should draw a gradient or not
  66.      */
  67.     private boolean drawGradient = false;
  68.     /**
  69.      * <p>If true, then the gradient will track the width of the panel. For example,
  70.      * if I had the following gradient paint:
  71.      * <code>
  72.      *  int width = getWidth();
  73.      *  GradientPaint gp = new GradientPaint(0, 0, Color.BLUE, width, 0, Color.WHITE);
  74.      * </code>
  75.      * Then at the left edge of the component BLUE will be painted, and at the
  76.      * right edge WHITE will be painted with a nice gradient between. However,
  77.      * when the width of the JXPanel changes, the &quot;width&quot; of the
  78.      * GradientPaint does not since GradientPaint is immutable.</p>
  79.      *
  80.      * <p>To solve this problem, the JXPanel employs a unique algorithm. Consider
  81.      * the following gradients on a panel with a width of 5 and a height of 5:
  82.      * <code>
  83.      * GradientPaint a = new GradientPaint(0, 0, Color.BLUE, 5, 0, Color.WHITE);
  84.      * GradientPaint b = new GradientPaint(0, 0, Color.BLUE, 10, 0, Color.WHITE);
  85.      * </code></p>
  86.      *
  87.      * <p>GradientPaint &quot;a&quot; would paint a BLUE vertical line at x position 0, and
  88.      * a WHITE vertical line at x position 5, with a gradient of colors between.
  89.      *
  90.      * <p>GradientPaint &quot;b&quot; would paint a BLUE vertical line at x position 0, and
  91.      * a WHITE vertical line at x position 10 which is outside the clipping
  92.      * bounds, and thus not actually painted! The color at x position 5 would be
  93.      * halfway between BLUE and WHITE.</p>
  94.      *
  95.      * <p>If the JXPanel was then resized to be 10 pixels wide and 10 pixels tall,
  96.      * we would expect to see the gradient paints be updated like to be these:
  97.      * <code>
  98.      * GradientPaint a = new GradientPaint(0, 0, Color.BLUE, 10, 0, Color.WHITE);
  99.      * GradientPaint b = new GradientPaint(0, 0, Color.BLUE, 20, 0, Color.WHITE);
  100.      * </code></p>
  101.      *
  102.      * <p>This is exactly what happens. Whatever GradientPaint is set by the
  103.      * <code>setGradientPaint</code> method is assumed to be in terms of the
  104.      * current width and height of the component. As the component&apos;s size
  105.      * changes, the GradientPaint is updated proportionately to the change so that
  106.      * the color drawn at position 0 and at position N where N is the width/height
  107.      * will be consistent regardless of the changes in dimension of the component.</p>
  108.      */
  109.     private boolean gradientTrackWidth = true;
  110.     /**
  111.      * same as gradientTrackWidth, but in the vertical direction
  112.      */
  113.     private boolean gradientTrackHeight = true;
  114.     /**
  115.      * If the JXPanel is to draw a gradient, this paint indicates how it should
  116.      * be painted
  117.      */
  118.     private GradientPaint gradientPaint;
  119.     /**
  120.      * Keeps track of the old dimensions so that if the dimensions change, the
  121.      * saved gradient image can be thrown out and re-rendered. This size is
  122.      * AFTER applying the insets!
  123.      */
  124.     private Dimension oldSize;
  125.     /**
  126.      * The cached gradient image
  127.      */
  128.     private BufferedImage cachedGradient;
  129.     
  130.     /** 
  131.      * Creates a new instance of JXPanel
  132.      */
  133.     public JXPanel() {
  134.     }
  135.     
  136.     /**
  137.      * @param isDoubleBuffered
  138.      */
  139.     public JXPanel(boolean isDoubleBuffered) {
  140.         super(isDoubleBuffered);
  141.     }
  142.     /**
  143.      * @param layout
  144.      */
  145.     public JXPanel(LayoutManager layout) {
  146.         super(layout);
  147.     }
  148.     /**
  149.      * @param layout
  150.      * @param isDoubleBuffered
  151.      */
  152.     public JXPanel(LayoutManager layout, boolean isDoubleBuffered) {
  153.         super(layout, isDoubleBuffered);
  154.     }
  155.     
  156.     /**
  157.      * Set the alpha transparency level for this component. This automatically
  158.      * causes a repaint of the component.
  159.      * 
  160.      * <p>TODO add support for animated changes in translucency</p>
  161.      *
  162.      * @param alpha must be a value between 0 and 1 inclusive.
  163.      */
  164.     public void setAlpha(float alpha) {
  165.         if (this.alpha != alpha) {
  166.             assert alpha >= 0 && alpha <= 1.0;
  167.             float oldAlpha = this.alpha;
  168.             this.alpha = alpha;
  169.             if (alpha > 0f && alpha < 1f) {
  170.                 if (oldAlpha == 1) {
  171.                     //it used to be 1, but now is not. Save the oldOpaque
  172.                     oldOpaque = isOpaque();
  173.                     setOpaque(false);
  174.                 }
  175.                 if (!(RepaintManager.currentManager(this) instanceof TranslucentRepaintManager)) {
  176.                     RepaintManager.setCurrentManager(new RepaintManagerX());
  177.                 }
  178.             } else if (alpha == 1) {
  179.                 //restore the oldOpaque if it was true (since opaque is false now)
  180.                 if (oldOpaque) {
  181.                    setOpaque(true);
  182.                 }
  183.             }
  184.             firePropertyChange("alpha", oldAlpha, alpha);
  185.             repaint();
  186.         }
  187.     }
  188.     
  189.     /**
  190.      * @return the alpha translucency level for this component. This will be
  191.      * a value between 0 and 1, inclusive.
  192.      */
  193.     public float getAlpha() {
  194.         return alpha;
  195.     }
  196.     /**
  197.      * Unlike other properties, alpha can be set on a component, or on one of
  198.      * its parents. If the alpha of a parent component is .4, and the alpha on
  199.      * this component is .5, effectively the alpha for this component is .4
  200.      * because the lowest alpha in the heirarchy &quot;wins&quot;
  201.      */ 
  202.     public float getEffectiveAlpha() {
  203.         if (inheritAlpha) {
  204.             float a = alpha;
  205.             Component c = this;
  206.             while ((c = c.getParent()) != null) {
  207.                 if (c instanceof JXPanel) {
  208.                     a = Math.min(((JXPanel)c).getAlpha(), a);
  209.                 }
  210.             }
  211.             return a;
  212.         } else {
  213.             return alpha;
  214.         }
  215.     }
  216.     
  217.     public boolean isInheritAlpha() {
  218.         return inheritAlpha;
  219.     }
  220.     
  221.     public void setInheritAlpha(boolean val) {
  222.         if (inheritAlpha != val) {
  223.             inheritAlpha = val;
  224.             firePropertyChange("inheritAlpha", !inheritAlpha, inheritAlpha);
  225.         }
  226.     }
  227.     
  228.     /* (non-Javadoc)
  229.      * @see javax.swing.Scrollable#getScrollableTracksViewportHeight()
  230.      */
  231.     public boolean getScrollableTracksViewportHeight() {
  232.         return scrollableTracksViewportHeight;
  233.     }
  234.     
  235.     /* (non-Javadoc)
  236.      * @see javax.swing.Scrollable#getScrollableTracksViewportWidth()
  237.      */
  238.     public boolean getScrollableTracksViewportWidth() {
  239.         return scrollableTracksViewportWidth;
  240.     }
  241.     
  242.     /* (non-Javadoc)
  243.      * @see javax.swing.Scrollable#getPreferredScrollableViewportSize()
  244.      */
  245.     public Dimension getPreferredScrollableViewportSize() {
  246.         return getPreferredSize();
  247.     }
  248.     
  249.     /* (non-Javadoc)
  250.      * @see javax.swing.Scrollable#getScrollableBlockIncrement(java.awt.Rectangle, int, int)
  251.      */
  252.     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
  253.         return 10;
  254.     }
  255.     
  256.     /* (non-Javadoc)
  257.      * @see javax.swing.Scrollable#getScrollableUnitIncrement(java.awt.Rectangle, int, int)
  258.      */
  259.     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
  260.         return 10;
  261.     }
  262.     /**
  263.      * @param scrollableTracksViewportHeight The scrollableTracksViewportHeight to set.
  264.      */
  265.     public void setScrollableTracksViewportHeight(boolean scrollableTracksViewportHeight) {
  266.         this.scrollableTracksViewportHeight = scrollableTracksViewportHeight;
  267.     }
  268.     /**
  269.      * @param scrollableTracksViewportWidth The scrollableTracksViewportWidth to set.
  270.      */
  271.     public void setScrollableTracksViewportWidth(boolean scrollableTracksViewportWidth) {
  272.         this.scrollableTracksViewportWidth = scrollableTracksViewportWidth;
  273.     }
  274.     public void setGradientPaint(GradientPaint paint) {
  275.         GradientPaint oldPaint = this.gradientPaint;
  276.         this.gradientPaint = paint;
  277.         firePropertyChange("gradientPaint", oldPaint, paint);
  278.         repaint();
  279.     }
  280.     
  281.     public GradientPaint getGradientPaint() {
  282.         return gradientPaint;
  283.     }
  284.     
  285.     public void setDrawGradient(boolean b) {
  286.         if (drawGradient != b) {
  287.             boolean old = drawGradient;
  288.             drawGradient = b;
  289.             oldSize = getSize();
  290.             firePropertyChange("drawGradient", old, b);
  291.             repaint();
  292.         }
  293.     }
  294.     
  295.     public boolean isDrawGradient() {
  296.         return drawGradient;
  297.     }
  298.     
  299.     public void setGradientTrackWidth(boolean b) {
  300.         if (gradientTrackWidth != b) {
  301.             boolean old = gradientTrackWidth;
  302.             gradientTrackWidth = b;
  303.             firePropertyChange("gradientTrackWidth", old, b);
  304.             repaint();
  305.         }
  306.     }
  307.     
  308.     public boolean isGradientTrackWidth() {
  309.         return gradientTrackWidth;
  310.     }
  311.     
  312.     public void setGradientTrackHeight(boolean b) {
  313.         if (gradientTrackHeight != b) {
  314.             boolean old = gradientTrackHeight;
  315.             gradientTrackHeight = b;
  316.             firePropertyChange("gradientTrackHeight", old, b);
  317.             repaint();
  318.         }
  319.     }
  320.     
  321.     public boolean isGradientTrackHeight() {
  322.         return gradientTrackHeight;
  323.     }
  324.     
  325.     /**
  326.      * Overriden paint method to take into account the alpha setting
  327.      */
  328.     public void paint(Graphics g) {
  329.         Graphics2D g2d = (Graphics2D)g;
  330.         Composite oldComp = g2d.getComposite();
  331.         float alpha = getEffectiveAlpha();
  332.         Composite alphaComp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
  333.         g2d.setComposite(alphaComp);
  334.         super.paint(g2d);
  335.         g2d.setComposite(oldComp);
  336.     }
  337.     /**
  338.      * overridden to provide gradient painting
  339.      *
  340.      * TODO: Chris says that in OGL we actually suffer here by caching the
  341.      * gradient paint since the OGL pipeline will render gradients on
  342.      * hardware for us. The decision to use cacheing is based on my experience
  343.      * with gradient title borders slowing down repaints -- this could use more
  344.      * extensive analysis.
  345.      */
  346.     protected void paintComponent(Graphics g) {
  347.         super.paintComponent(g);
  348.         if (drawGradient) {
  349.             Insets insets = getInsets();
  350.             int width = getWidth() - insets.right - insets.left;
  351.             int height = getHeight() - insets.top - insets.bottom;
  352.             
  353.             //TODO need to detect a change in gradient paint as well
  354.             if (gradientPaint == null || oldSize == null || oldSize.width != width || oldSize.height != height) {
  355.                 Color c1 = null;//UIManager.getColor("control");
  356.                 Color c2 = null;//c.darker();
  357.                 if (gradientPaint == null) {
  358.                     c1 = getBackground();
  359.                     c2 = new Color(c1.getRed() - 40, c1.getGreen() - 40, c1.getBlue() - 40);
  360.                     float x1 = 0f;
  361.                     float y1 = 0f;
  362.                     float x2 = width;
  363.                     float y2 = 0;
  364.                     boolean cyclic = false;
  365.                     gradientPaint = new GradientPaint(x1, y1, c1, x2, y2, c2, cyclic);
  366.                 } else {
  367.                     //same GP as before, but where the values differed for x1, x2, replace
  368.                     //x2 with the current width, and where values differed for y1, y2
  369.                     //replace with current height
  370.                     GradientPaint gp = gradientPaint;
  371.                     float x2 = (float)gp.getPoint2().getX();
  372.                     if (gradientTrackWidth) {
  373.                         float ratio = (float)width / (float)oldSize.width;
  374.                         x2 = ((float)gp.getPoint2().getX()) * ratio;
  375.                     }
  376.                     float y2 = (float)gp.getPoint2().getY();
  377.                     if (gradientTrackHeight) {
  378.                         float ratio = (float)height / (float)oldSize.height;
  379.                         y2 = ((float)gp.getPoint2().getY()) * ratio;
  380.                     }
  381.                     gradientPaint = new GradientPaint((float)gp.getPoint1().getX(),
  382.                             (float)gp.getPoint1().getY(), gp.getColor1(),
  383.                             x2, y2, gp.getColor2(),
  384.                             gp.isCyclic());
  385.                 }
  386.                 
  387.                 oldSize = new Dimension(width, height);
  388.                 cachedGradient = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
  389.                 Graphics2D imgg = (Graphics2D)cachedGradient.getGraphics();
  390.                 imgg.setPaint(gradientPaint);
  391.                 imgg.fillRect(0, 0, width, height);
  392.             }
  393.             // draw the image
  394.             Graphics2D g2 = (Graphics2D)g;
  395.             g2.drawImage(cachedGradient, null, insets.left, insets.top);
  396.         }
  397.     }
  398. }