1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing;
  26 
  27 import java.awt.*;
  28 import java.awt.event.*;
  29 import java.io.*;
  30 import java.beans.PropertyChangeListener;
  31 import java.util.Locale;
  32 import java.util.Vector;
  33 
  34 import javax.accessibility.*;
  35 
  36 /**
  37  * This class is inserted in between cell renderers and the components that
  38  * use them.  It just exists to thwart the repaint() and invalidate() methods
  39  * which would otherwise propagate up the tree when the renderer was configured.
  40  * It's used by the implementations of JTable, JTree, and JList.  For example,
  41  * here's how CellRendererPane is used in the code the paints each row
  42  * in a JList:
  43  * <pre>
  44  *   cellRendererPane = new CellRendererPane();
  45  *   ...
  46  *   Component rendererComponent = renderer.getListCellRendererComponent();
  47  *   renderer.configureListCellRenderer(dataModel.getElementAt(row), row);
  48  *   cellRendererPane.paintComponent(g, rendererComponent, this, x, y, w, h);
  49  * </pre>
  50  * <p>
  51  * A renderer component must override isShowing() and unconditionally return
  52  * true to work correctly because the Swing paint does nothing for components
  53  * with isShowing false.
  54  * <p>
  55  * <strong>Warning:</strong>
  56  * Serialized objects of this class will not be compatible with
  57  * future Swing releases. The current serialization support is
  58  * appropriate for short term storage or RMI between applications running
  59  * the same version of Swing.  As of 1.4, support for long term storage
  60  * of all JavaBeans
  61  * has been added to the <code>java.beans</code> package.
  62  * Please see {@link java.beans.XMLEncoder}.
  63  *
  64  * @author Hans Muller
  65  * @since 1.2
  66  */
  67 @SuppressWarnings("serial") // Same-version serialization only
  68 public class CellRendererPane extends Container implements Accessible
  69 {
  70     /**
  71      * Construct a CellRendererPane object.
  72      */
  73     public CellRendererPane() {
  74         super();
  75         setLayout(null);
  76         setVisible(false);
  77     }
  78 
  79     /**
  80      * Overridden to avoid propagating a invalidate up the tree when the
  81      * cell renderer child is configured.
  82      */
  83     public void invalidate() { }
  84 
  85 
  86     /**
  87      * Shouldn't be called.
  88      */
  89     public void paint(Graphics g) { }
  90 
  91 
  92     /**
  93      * Shouldn't be called.
  94      */
  95     public void update(Graphics g) { }
  96 
  97 
  98     /**
  99      * If the specified component is already a child of this then we don't
 100      * bother doing anything - stacking order doesn't matter for cell
 101      * renderer components (CellRendererPane doesn't paint anyway).
 102      */
 103     protected void addImpl(Component x, Object constraints, int index) {
 104         if (x.getParent() == this) {
 105             return;
 106         }
 107         else {
 108             super.addImpl(x, constraints, index);
 109         }
 110     }
 111 
 112 
 113     /**
 114      * Paint a cell renderer component c on graphics object g.  Before the component
 115      * is drawn it's reparented to this (if that's necessary), it's bounds
 116      * are set to w,h and the graphics object is (effectively) translated to x,y.
 117      * If it's a JComponent, double buffering is temporarily turned off. After
 118      * the component is painted it's bounds are reset to -w, -h, 0, 0 so that, if
 119      * it's the last renderer component painted, it will not start consuming input.
 120      * The Container p is the component we're actually drawing on, typically it's
 121      * equal to this.getParent(). If shouldValidate is true the component c will be
 122      * validated before painted.
 123      *
 124      * @param g  the {@code Graphics} object to draw on
 125      * @param c  the {@code Component} to draw
 126      * @param p  the {@code Container} component actually drawn on
 127      * @param x  an int specifying the left side of the area draw in, in pixels,
 128      *           measured from the left edge of the graphics context
 129      * @param y  an int specifying the top of the area to draw in, in pixels
 130      *           measured down from the top edge of the graphics context
 131      * @param w  an int specifying the width of the area draw in, in pixels
 132      * @param h  an int specifying the height of the area draw in, in pixels
 133      * @param shouldValidate  if true, component {@code c} will be validated
 134      *                        before being painted
 135      */
 136     public void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h, boolean shouldValidate) {
 137         if (c == null) {
 138             if (p != null) {
 139                 Color oldColor = g.getColor();
 140                 g.setColor(p.getBackground());
 141                 g.fillRect(x, y, w, h);
 142                 g.setColor(oldColor);
 143             }
 144             return;
 145         }
 146 
 147         if (c.getParent() != this) {
 148             this.add(c);
 149         }
 150 
 151         c.setBounds(x, y, w, h);
 152 
 153         if(shouldValidate) {
 154             c.validate();
 155         }
 156 
 157         boolean wasDoubleBuffered = false;
 158         if ((c instanceof JComponent) && ((JComponent)c).isDoubleBuffered()) {
 159             wasDoubleBuffered = true;
 160             ((JComponent)c).setDoubleBuffered(false);
 161         }
 162 
 163         Graphics cg = g.create(x, y, w, h);
 164         try {
 165             c.paint(cg);
 166         }
 167         finally {
 168             cg.dispose();
 169         }
 170 
 171         if (wasDoubleBuffered && (c instanceof JComponent)) {
 172             ((JComponent)c).setDoubleBuffered(true);
 173         }
 174 
 175         c.setBounds(-w, -h, 0, 0);
 176     }
 177 
 178 
 179     /**
 180      * Calls this.paintComponent(g, c, p, x, y, w, h, false).
 181      *
 182      * @param g  the {@code Graphics} object to draw on
 183      * @param c  the {@code Component} to draw
 184      * @param p  the {@code Container} component actually drawn on
 185      * @param x  an int specifying the left side of the area draw in, in pixels,
 186      *           measured from the left edge of the graphics context
 187      * @param y  an int specifying the top of the area to draw in, in pixels
 188      *           measured down from the top edge of the graphics context
 189      * @param w  an int specifying the width of the area draw in, in pixels
 190      * @param h  an int specifying the height of the area draw in, in pixels
 191      */
 192     public void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h) {
 193         paintComponent(g, c, p, x, y, w, h, false);
 194     }
 195 
 196 
 197     /**
 198      * Calls this.paintComponent() with the rectangles x,y,width,height fields.
 199      *
 200      * @param g  the {@code Graphics} object to draw on
 201      * @param c  the {@code Component} to draw
 202      * @param p  the {@code Container} component actually drawn on
 203      * @param r  the {@code Rectangle} to draw in
 204      */
 205     public void paintComponent(Graphics g, Component c, Container p, Rectangle r) {
 206         paintComponent(g, c, p, r.x, r.y, r.width, r.height);
 207     }
 208 
 209 
 210     private void writeObject(ObjectOutputStream s) throws IOException {
 211         removeAll();
 212         s.defaultWriteObject();
 213     }
 214 
 215 
 216 /////////////////
 217 // Accessibility support
 218 ////////////////
 219 
 220     /**
 221      * {@code AccessibleContext} associated with this {@code CellRendererPan}
 222      */
 223     protected AccessibleContext accessibleContext = null;
 224 
 225 
 226     /**
 227      * Gets the AccessibleContext associated with this CellRendererPane.
 228      * For CellRendererPanes, the AccessibleContext takes the form of an
 229      * AccessibleCellRendererPane.
 230      * A new AccessibleCellRendererPane instance is created if necessary.
 231      *
 232      * @return an AccessibleCellRendererPane that serves as the
 233      *         AccessibleContext of this CellRendererPane
 234      */
 235     public AccessibleContext getAccessibleContext() {
 236         if (accessibleContext == null) {
 237             accessibleContext = new AccessibleCellRendererPane();
 238         }
 239         return accessibleContext;
 240     }
 241 
 242     /**
 243      * This class implements accessibility support for the
 244      * <code>CellRendererPane</code> class.
 245      */
 246     protected class AccessibleCellRendererPane extends AccessibleAWTContainer {
 247         // AccessibleContext methods
 248         //
 249         /**
 250          * Get the role of this object.
 251          *
 252          * @return an instance of AccessibleRole describing the role of the
 253          * object
 254          * @see AccessibleRole
 255          */
 256         public AccessibleRole getAccessibleRole() {
 257             return AccessibleRole.PANEL;
 258         }
 259     } // inner class AccessibleCellRendererPane
 260 }