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

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: BasicTitledPanelUI.java,v 1.10 2005/10/10 18:02:52 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.plaf.basic;
  22. import java.awt.BorderLayout;
  23. import java.awt.Color;
  24. import java.awt.Container;
  25. import java.awt.Font;
  26. import java.awt.GradientPaint;
  27. import java.awt.Graphics;
  28. import java.awt.Graphics2D;
  29. import java.awt.GridBagConstraints;
  30. import java.awt.GridBagLayout;
  31. import java.awt.Image;
  32. import java.awt.Insets;
  33. import java.beans.BeanInfo;
  34. import java.beans.Introspector;
  35. import java.beans.PropertyChangeEvent;
  36. import java.beans.PropertyChangeListener;
  37. import java.beans.PropertyDescriptor;
  38. import java.lang.reflect.Method;
  39. import javax.swing.BorderFactory;
  40. import javax.swing.ImageIcon;
  41. import javax.swing.JComponent;
  42. import javax.swing.JLabel;
  43. import javax.swing.UIManager;
  44. import javax.swing.plaf.UIResource;
  45. import org.jdesktop.swingx.JXPanel;
  46. import org.jdesktop.swingx.JXTitledPanel;
  47. import org.jdesktop.swingx.plaf.TitledPanelUI;
  48. /**
  49.  * All TitledPanels contain a title section and a content section. The default
  50.  * implementation for the title section relies on a Gradient background. All
  51.  * title sections can have components embedded to the "left" or
  52.  * "right" of the Title.
  53.  *
  54.  * @author Richard Bair
  55.  * @author Jeanette Winzenburg
  56.  * 
  57.  */
  58. public abstract class BasicTitledPanelUI extends TitledPanelUI {
  59.     
  60.     
  61. /**
  62.  * JLabel used for the title in the Title section of the JTitledPanel.
  63.  */
  64. private JLabel caption;
  65. /**
  66.  * The Title section panel.
  67.  */
  68. private JGradientPanel topPanel;
  69.     /**
  70.      * Listens to changes in the title of the JXTitledPanel component
  71.      */
  72.     private PropertyChangeListener titleChangeListener;
  73.     /**
  74.      * The JXTitledPanel peered with this UI
  75.      */
  76.     protected JXTitledPanel titledPanel;
  77.     private JComponent left;
  78.     private JComponent right;
  79.     
  80.     /** Creates a new instance of BasicTitledPanelUI */
  81.     public BasicTitledPanelUI() {
  82.     }
  83.     /**
  84.      * Configures the specified component appropriate for the look and feel.
  85.      * This method is invoked when the <code>ComponentUI</code> instance is being installed
  86.      * as the UI delegate on the specified component.  This method should
  87.      * completely configure the component for the look and feel,
  88.      * including the following:
  89.      * <ol>
  90.      * <li>Install any default property values for color, fonts, borders,
  91.      *     icons, opacity, etc. on the component.  Whenever possible, 
  92.      *     property values initialized by the client program should <i>not</i> 
  93.      *     be overridden.
  94.      * <li>Install a <code>LayoutManager</code> on the component if necessary.
  95.      * <li>Create/add any required sub-components to the component.
  96.      * <li>Create/install event listeners on the component.
  97.      * <li>Create/install a <code>PropertyChangeListener</code> on the component in order
  98.      *     to detect and respond to component property changes appropriately.
  99.      * <li>Install keyboard UI (mnemonics, traversal, etc.) on the component.
  100.      * <li>Initialize any appropriate instance data.
  101.      * </ol>
  102.      * @param c the component where this UI delegate is being installed
  103.      *
  104.      * @see #uninstallUI
  105.      * @see javax.swing.JComponent#setUI
  106.      * @see javax.swing.JComponent#updateUI
  107.      */
  108.     public void installUI(JComponent c) {
  109.         assert c instanceof JXTitledPanel;
  110.         titledPanel = (JXTitledPanel)c;
  111.         
  112.         installProperty(titledPanel, "titleForeground", UIManager.getColor("JXTitledPanel.title.foreground"));
  113.         installProperty(titledPanel, "titleDarkBackground", UIManager.getColor("JXTitledPanel.title.darkBackground"));
  114.         installProperty(titledPanel, "titleLightBackground", UIManager.getColor("JXTitledPanel.title.lightBackground"));
  115.         installProperty(titledPanel, "titleFont", UIManager.getFont("JXTitledPanel.title.font"));
  116.         
  117.       caption = createAndConfigureCaption(titledPanel);
  118.       topPanel = createAndConfigureTopPanel(titledPanel);
  119.         fillTopPanel();
  120.         titledPanel.setLayout(new BorderLayout());
  121.         titledPanel.add(topPanel, BorderLayout.NORTH);
  122. titledPanel.setBorder(BorderFactory.createRaisedBevelBorder());
  123. titledPanel.setOpaque(false);
  124.         
  125.         installListeners();
  126.         
  127.     }
  128.     private void fillTopPanel() {
  129.         topPanel.add(caption, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(4, 12, 4, 12), 0, 0));
  130.         if (titledPanel.getClientProperty(JXTitledPanel.RIGHT_DECORATION) instanceof JComponent) {
  131.             addRightDecoration((JComponent) titledPanel.getClientProperty(JXTitledPanel.RIGHT_DECORATION));
  132.         }
  133.         if (titledPanel.getClientProperty(JXTitledPanel.LEFT_DECORATION) instanceof JComponent) {
  134.             addLeftDecoration((JComponent) titledPanel.getClientProperty(JXTitledPanel.LEFT_DECORATION));
  135.         }
  136.     }
  137.     private JGradientPanel createAndConfigureTopPanel(JXTitledPanel titledPanel) {
  138.         JGradientPanel topPanel = createTopPanel(titledPanel);
  139.         topPanel.setBorder(BorderFactory.createEmptyBorder());
  140.         topPanel.setLayout(new GridBagLayout());
  141.         return topPanel;
  142.     }
  143.     private JLabel createAndConfigureCaption(JXTitledPanel titledPanel) {
  144.         JLabel caption = new JLabel(titledPanel.getTitle());
  145.         caption.setFont(titledPanel.getTitleFont());
  146.         caption.setForeground(titledPanel.getTitleForeground());
  147.         return caption;
  148.     }
  149.     /**
  150.      * Reverses configuration which was done on the specified component during
  151.      * <code>installUI</code>.  This method is invoked when this 
  152.      * <code>UIComponent</code> instance is being removed as the UI delegate 
  153.      * for the specified component.  This method should undo the
  154.      * configuration performed in <code>installUI</code>, being careful to 
  155.      * leave the <code>JComponent</code> instance in a clean state (no 
  156.      * extraneous listeners, look-and-feel-specific property objects, etc.).
  157.      * This should include the following:
  158.      * <ol>
  159.      * <li>Remove any UI-set borders from the component.
  160.      * <li>Remove any UI-set layout managers on the component.
  161.      * <li>Remove any UI-added sub-components from the component.
  162.      * <li>Remove any UI-added event/property listeners from the component.
  163.      * <li>Remove any UI-installed keyboard UI from the component.
  164.      * <li>Nullify any allocated instance data objects to allow for GC.
  165.      * </ol>
  166.      * @param c the component from which this UI delegate is being removed;
  167.      *          this argument is often ignored,
  168.      *          but might be used if the UI object is stateless
  169.      *          and shared by multiple components
  170.      *
  171.      * @see #installUI
  172.      * @see javax.swing.JComponent#updateUI
  173.      */
  174.     public void uninstallUI(JComponent c) {
  175.         assert c instanceof JXTitledPanel;
  176.         uninstallListeners(titledPanel);
  177.         // JW: this is needed to make the gradient paint work correctly... 
  178.         // LF changes will remove the left/right components...
  179.         topPanel.removeAll();
  180.         titledPanel.remove(topPanel);
  181.         titledPanel.putClientProperty(JXTitledPanel.LEFT_DECORATION, left);
  182.         titledPanel.putClientProperty(JXTitledPanel.RIGHT_DECORATION, right);
  183.         caption =  null;
  184.         topPanel = null;
  185.         titledPanel = null;
  186.         left = null;
  187.         right = null;
  188.     }
  189.     protected void installListeners() {
  190.         titleChangeListener = new PropertyChangeListener() {
  191.             public void propertyChange(PropertyChangeEvent evt) {
  192.                 if (evt.getPropertyName().equals("title")) {
  193.                     caption.setText((String)evt.getNewValue());
  194.                 } else if (evt.getPropertyName().equals("titleForeground")) {
  195.                     caption.setForeground((Color)evt.getNewValue());
  196.                 } else if (evt.getPropertyName().equals("titleFont")) {
  197.                     caption.setFont((Font)evt.getNewValue());
  198.                 } else if ("titleDarkBackground".equals(evt.getPropertyName())) {
  199.                     topPanel.revalidateGradient();
  200.                
  201.             } else if ("titleLightBackground".equals(evt.getPropertyName())) {
  202.                 topPanel.revalidateGradient();
  203.             }
  204.             }
  205.         };
  206.         titledPanel.addPropertyChangeListener(titleChangeListener);
  207.     }
  208.     protected void uninstallListeners(JXTitledPanel panel) {
  209.         titledPanel.removePropertyChangeListener(titleChangeListener);
  210.     }
  211.     protected void installProperty(JComponent c, String propName, Object value) {
  212.         try {
  213.             BeanInfo bi = Introspector.getBeanInfo(c.getClass());
  214.             for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
  215.                 if (pd.getName().equals(propName)) {
  216.                     Method m = pd.getReadMethod();
  217.                     Object oldVal = m.invoke(c);
  218.                     if (oldVal == null || oldVal instanceof UIResource) {
  219.                         m = pd.getWriteMethod();
  220.                         m.invoke(c, value);
  221.                     }
  222.                 }
  223.             }
  224.         } catch (Exception e) {
  225.             //should log this...TODO
  226.             e.printStackTrace();
  227.         }
  228.     }
  229.     /**
  230.      * Paints the specified component appropriate for the look and feel.
  231.      * This method is invoked from the <code>ComponentUI.update</code> method when 
  232.      * the specified component is being painted.  Subclasses should override 
  233.      * this method and use the specified <code>Graphics</code> object to 
  234.      * render the content of the component.
  235.      *
  236.      * @param g the <code>Graphics</code> context in which to paint
  237.      * @param c the component being painted;
  238.      *          this argument is often ignored,
  239.      *          but might be used if the UI object is stateless
  240.      *          and shared by multiple components
  241.      *
  242.      * @see #update
  243.      */ 
  244.     public void paint(Graphics g, JComponent c) {
  245.         super.paint(g, c);
  246.     }
  247. /**
  248.  * Adds the given JComponent as a decoration on the right of the title
  249.  * @param decoration
  250.  */
  251. public void addRightDecoration(JComponent decoration) {
  252.         if (right != null) topPanel.remove(right);
  253.         right = decoration;
  254.         if (right != null) {
  255. topPanel.add(decoration, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
  256.         }
  257.     }
  258. /**
  259.  * Adds the given JComponent as a decoration on the left of the title
  260.  * @param decoration
  261.  */
  262. public void addLeftDecoration(JComponent decoration) {
  263.         if (left != null) topPanel.remove(left);
  264.         left = decoration;
  265.         if (left != null) {
  266.             topPanel.add(left, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
  267.         }
  268. }
  269.     /**
  270.      * @return the Container acting as the title bar for this component
  271.      */
  272.     public Container getTitleBar() {
  273.         return topPanel;
  274.     }
  275.     protected JGradientPanel createTopPanel(JXTitledPanel panel) {
  276.         return new JGradientPanel(panel);
  277.     }
  278.     
  279.     /**
  280.  * A special inner class who's background is painted as a gradient.  This is used
  281.  * as the Title section of the JTitledPanel
  282.  * @author Richard Bair
  283.  * date: Jan 13, 2004
  284.  */
  285. protected static 
  286.     class JGradientPanel extends JXPanel {
  287. private GradientPaint gp;
  288. private double oldWidth = -1;
  289. private double oldHeight = -1;
  290. private ImageIcon helper = new ImageIcon();
  291.         private JXTitledPanel titledPanel;
  292. public JGradientPanel(JXTitledPanel panel) {
  293.             this.titledPanel = panel;
  294. }
  295.         public void invalidateGradient() {
  296.             gp = null;
  297.         }
  298.         public void revalidateGradient() {
  299.             invalidateGradient();
  300.             repaint();
  301.         }
  302. //override the background color to provide for a gradient
  303. /* (non-Javadoc)
  304.  * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
  305.  * 
  306.  * There is some special optimization code in here that is kind of...er..shall we say, tricky.
  307.  * First off, the gradient panels are taking forever to draw. Therefore, I have resorted to caching the
  308.  * gradient'ed paint job so that I don't have to repaint it all the time.
  309.  */
  310. protected void paintComponent(Graphics g) {
  311. //draw the gradient background
  312. if (gp == null || oldWidth != getWidth() || oldHeight != getHeight()) {
  313. gp = createGradientPaint();
  314. Image savedImg = createImage(getWidth(), getHeight());
  315. Graphics2D imgg = (Graphics2D)savedImg.getGraphics();
  316. imgg.setPaint(gp);
  317. imgg.fillRect(0, 0, getWidth(), getHeight());
  318. oldWidth = getWidth();
  319. oldHeight = getHeight();
  320. helper.setImage(savedImg);
  321. }
  322. // draw the image
  323. g.drawImage(helper.getImage(), 0, 0, getWidth(), getHeight(), helper.getImageObserver());
  324.             
  325.         }
  326.         
  327.         protected GradientPaint createGradientPaint() {
  328.             return new GradientPaint(0, 
  329.                                      0, 
  330.                                      titledPanel.getTitleDarkBackground(), 
  331.                                      getWidth(), 
  332.                                      0, 
  333.                                      titledPanel.getTitleLightBackground());
  334.         }
  335. }
  336. }