1. /*
  2. * @(#)CellRendererPane.java 1.29 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.io.*;
  11. import java.beans.PropertyChangeListener;
  12. import java.util.Locale;
  13. import java.util.Vector;
  14. import javax.accessibility.*;
  15. /**
  16. * This class is inserted in between cell renderers and the components that
  17. * use them. It just exists to thwart the repaint() and invalidate() methods
  18. * which would otherwise propogate up the tree when the renderer was configured.
  19. * It's used by the implementations of JTable, JTree, and JList. For example,
  20. * here's how CellRendererPane is used in the code the paints each row
  21. * in a JList:
  22. * <pre>
  23. * cellRendererPane = new CellRendererPane();
  24. * ...
  25. * Component rendererComponent = renderer.getListCellRendererComponent();
  26. * renderer.configureListCellRenderer(dataModel.getElementAt(row), row);
  27. * cellRendererPane.paintComponent(g, rendererComponent, this, x, y, w, h);
  28. * </pre>
  29. * <p>
  30. * A renderer component must override isShowing() and unconditionally return
  31. * true to work correctly because the Swing paint does nothing for components
  32. * with isShowing false.
  33. * <p>
  34. * <strong>Warning:</strong>
  35. * Serialized objects of this class will not be compatible with
  36. * future Swing releases. The current serialization support is appropriate
  37. * for short term storage or RMI between applications running the same
  38. * version of Swing. A future release of Swing will provide support for
  39. * long term persistence.
  40. *
  41. * @version 1.29 11/29/01
  42. * @author Hans Muller
  43. */
  44. public class CellRendererPane extends Container implements Accessible
  45. {
  46. /**
  47. * Construct a CellRendererPane object.
  48. */
  49. public CellRendererPane() {
  50. super();
  51. setLayout(null);
  52. setVisible(false);
  53. }
  54. /**
  55. * Overridden to avoid propogating a invalidate up the tree when the
  56. * cell renderer child is configured.
  57. */
  58. public void invalidate() { }
  59. /**
  60. * Shouldn't be called.
  61. */
  62. public void paint(Graphics g) { }
  63. /**
  64. * Shouldn't be called.
  65. */
  66. public void update(Graphics g) { }
  67. /**
  68. * If the specified component is already a child of this then we don't
  69. * bother doing anything - stacking order doesn't matter for cell
  70. * renderer components (CellRendererPane doesn't paint anyway).<
  71. */
  72. protected void addImpl(Component x, Object constraints, int index) {
  73. if (x.getParent() == this) {
  74. return;
  75. }
  76. else {
  77. super.addImpl(x, constraints, index);
  78. }
  79. }
  80. /**
  81. * Paint a cell renderer component c on graphics object g. Before the component
  82. * is drawn it's reparented to this (if that's neccessary), it's bounds
  83. * are set to w,h and the graphics object is (effectively) translated to x,y.
  84. * If it's a JComponent, double buffering is temporarily turned off. After
  85. * the component is painted it's bounds are reset to -w, -h, 0, 0 so that, if
  86. * it's the last renderer component painted, it will not start consuming input.
  87. * The Container p is the component we're actually drawing on, typically it's
  88. * equal to this.getParent(). If shouldValidate is true the component c will be
  89. * validated before painted.
  90. */
  91. public void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h, boolean shouldValidate) {
  92. if (c == null) {
  93. if (p != null) {
  94. Color oldColor = g.getColor();
  95. g.setColor(p.getBackground());
  96. g.fillRect(x, y, w, h);
  97. g.setColor(oldColor);
  98. }
  99. return;
  100. }
  101. if (c.getParent() != this) {
  102. this.add(c);
  103. }
  104. c.setBounds(x, y, w, h);
  105. if(shouldValidate) {
  106. c.validate();
  107. }
  108. boolean wasDoubleBuffered = false;
  109. if ((c instanceof JComponent) && ((JComponent)c).isDoubleBuffered()) {
  110. wasDoubleBuffered = true;
  111. ((JComponent)c).setDoubleBuffered(false);
  112. }
  113. Graphics cg = SwingGraphics.createSwingGraphics(g, x, y, w, h);
  114. try {
  115. c.paint(cg);
  116. }
  117. finally {
  118. cg.dispose();
  119. }
  120. if ((c instanceof JComponent) && wasDoubleBuffered) {
  121. ((JComponent)c).setDoubleBuffered(true);
  122. }
  123. if (c instanceof JComponent) {
  124. JComponent jc = (JComponent)c;
  125. jc.setDoubleBuffered(wasDoubleBuffered);
  126. }
  127. c.setBounds(-w, -h, 0, 0);
  128. }
  129. /**
  130. * Calls this.paintComponent(g, c, p, x, y, w, h, false).
  131. */
  132. public void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h) {
  133. paintComponent(g, c, p, x, y, w, h, false);
  134. }
  135. /**
  136. * Calls this.paintComponent() with the rectangles x,y,width,height fields.
  137. */
  138. public void paintComponent(Graphics g, Component c, Container p, Rectangle r) {
  139. paintComponent(g, c, p, r.x, r.y, r.width, r.height);
  140. }
  141. private void writeObject(ObjectOutputStream s) throws IOException {
  142. removeAll();
  143. s.defaultWriteObject();
  144. }
  145. /////////////////
  146. // Accessibility support
  147. ////////////////
  148. protected AccessibleContext accessibleContext = null;
  149. /**
  150. * Get the AccessibleContext associated with this CellRendererPane
  151. *
  152. * @return the AccessibleContext of this CellRendererPane
  153. */
  154. public AccessibleContext getAccessibleContext() {
  155. if (accessibleContext == null) {
  156. accessibleContext = new AccessibleCellRendererPane();
  157. }
  158. return accessibleContext;
  159. }
  160. protected class AccessibleCellRendererPane extends AccessibleContext
  161. implements Serializable, AccessibleComponent
  162. {
  163. // AccessibleContext methods
  164. //
  165. /**
  166. * Get the role of this object.
  167. *
  168. * @return an instance of AccessibleRole describing the role of the
  169. * object
  170. * @see AccessibleRole
  171. */
  172. public AccessibleRole getAccessibleRole() {
  173. return AccessibleRole.PANEL;
  174. }
  175. /**
  176. * Get the state of this object.
  177. *
  178. * @return an instance of AccessibleStateSet containing the current
  179. * state set of the object
  180. * @see AccessibleState
  181. */
  182. public AccessibleStateSet getAccessibleStateSet() {
  183. return SwingUtilities.getAccessibleStateSet(CellRendererPane.this);
  184. }
  185. /**
  186. * Get the Accessible parent of this object. If the parent of this
  187. * object implements Accessible, this method should simply return
  188. * getParent().
  189. *
  190. * @return the Accessible parent of this object -- can be null if this
  191. * object does not have an Accessible parent
  192. */
  193. public Accessible getAccessibleParent() {
  194. if (accessibleParent != null) {
  195. return accessibleParent;
  196. } else {
  197. Container parent = getParent();
  198. if (parent instanceof Accessible) {
  199. return (Accessible) parent;
  200. }
  201. }
  202. return null;
  203. }
  204. /**
  205. * Get the index of this object in its accessible parent.
  206. *
  207. * @return the index of this object in its parent; -1 if this
  208. * object does not have an accessible parent.
  209. * @see #getAccessibleParent
  210. */
  211. public int getAccessibleIndexInParent() {
  212. return SwingUtilities.getAccessibleIndexInParent(CellRendererPane.this);
  213. }
  214. /**
  215. * Returns the number of accessible children in the object. If all
  216. * of the children of this object implement Accessible, than this
  217. * method should return the number of children of this object.
  218. *
  219. * @return the number of accessible children in the object.
  220. */
  221. public int getAccessibleChildrenCount() {
  222. return SwingUtilities.getAccessibleChildrenCount(CellRendererPane.this);
  223. }
  224. /**
  225. * Return the nth Accessible child of the object.
  226. *
  227. * @param i zero-based index of child
  228. * @return the nth Accessible child of the object
  229. */
  230. public Accessible getAccessibleChild(int i) {
  231. return SwingUtilities.getAccessibleChild(CellRendererPane.this,i);
  232. }
  233. /**
  234. * Return the locale of this object.
  235. *
  236. * @return the locale of this object
  237. */
  238. public Locale getLocale() {
  239. return CellRendererPane.this.getLocale();
  240. }
  241. /**
  242. * Get the AccessibleComponent associated with this object if one
  243. * exists. Otherwise return null.
  244. */
  245. public AccessibleComponent getAccessibleComponent() {
  246. return this;
  247. }
  248. // AccessibleComponent methods
  249. //
  250. /**
  251. * Get the background color of this object.
  252. *
  253. * @return the background color, if supported, of the object;
  254. * otherwise, null
  255. */
  256. public Color getBackground() {
  257. return CellRendererPane.this.getBackground();
  258. }
  259. /**
  260. * Set the background color of this object.
  261. *
  262. * @param c the new Color for the background
  263. */
  264. public void setBackground(Color c) {
  265. CellRendererPane.this.setBackground(c);
  266. }
  267. /**
  268. * Get the foreground color of this object.
  269. *
  270. * @return the foreground color, if supported, of the object;
  271. * otherwise, null
  272. */
  273. public Color getForeground() {
  274. return CellRendererPane.this.getForeground();
  275. }
  276. /**
  277. * Set the foreground color of this object.
  278. *
  279. * @param c the new Color for the foreground
  280. */
  281. public void setForeground(Color c) {
  282. CellRendererPane.this.setForeground(c);
  283. }
  284. /**
  285. * Get the Cursor of this object.
  286. *
  287. * @return the Cursor, if supported, of the object; otherwise, null
  288. */
  289. public Cursor getCursor() {
  290. return CellRendererPane.this.getCursor();
  291. }
  292. /**
  293. * Set the Cursor of this object.
  294. *
  295. * @param c the new Cursor for the object
  296. */
  297. public void setCursor(Cursor cursor) {
  298. CellRendererPane.this.setCursor(cursor);
  299. }
  300. /**
  301. * Get the Font of this object.
  302. *
  303. * @return the Font,if supported, for the object; otherwise, null
  304. */
  305. public Font getFont() {
  306. return CellRendererPane.this.getFont();
  307. }
  308. /**
  309. * Set the Font of this object.
  310. *
  311. * @param f the new Font for the object
  312. */
  313. public void setFont(Font f) {
  314. CellRendererPane.this.setFont(f);
  315. }
  316. /**
  317. * Get the FontMetrics of this object.
  318. *
  319. * @param f the Font
  320. * @return the FontMetrics, if supported, the object; otherwise, null
  321. * @see #getFont
  322. */
  323. public FontMetrics getFontMetrics(Font f) {
  324. return CellRendererPane.this.getFontMetrics(f);
  325. }
  326. /**
  327. * Determine if the object is enabled.
  328. *
  329. * @return true if object is enabled; otherwise, false
  330. */
  331. public boolean isEnabled() {
  332. return CellRendererPane.this.isEnabled();
  333. }
  334. /**
  335. * Set the enabled state of the object.
  336. *
  337. * @param b if true, enables this object; otherwise, disables it
  338. */
  339. public void setEnabled(boolean b) {
  340. CellRendererPane.this.setEnabled(b);
  341. }
  342. /**
  343. * Determine if the object is visible. Note: this means that the
  344. * object intends to be visible; however, it may not in fact be
  345. * showing on the screen because one of the objects that this object
  346. * is contained by is not visible. To determine if an object is
  347. * showing on the screen, use isShowing().
  348. *
  349. * @return true if object is visible; otherwise, false
  350. */
  351. public boolean isVisible() {
  352. return CellRendererPane.this.isVisible();
  353. }
  354. /**
  355. * Set the visible state of the object.
  356. *
  357. * @param b if true, shows this object; otherwise, hides it
  358. */
  359. public void setVisible(boolean b) {
  360. CellRendererPane.this.setVisible(b);
  361. }
  362. /**
  363. * Determine if the object is showing. This is determined by checking
  364. * the visibility of the object and ancestors of the object. Note:
  365. * this will return true even if the object is obscured by another
  366. * (for example, it happens to be underneath a menu that was pulled
  367. * down).
  368. *
  369. * @return true if object is showing; otherwise, false
  370. */
  371. public boolean isShowing() {
  372. return CellRendererPane.this.isShowing();
  373. }
  374. /**
  375. * Checks whether the specified point is within this object's bounds,
  376. * where the point's x and y coordinates are defined to be relative to
  377. * the coordinate system of the object.
  378. *
  379. * @param p the Point relative to the coordinate system of the object
  380. * @return true if object contains Point; otherwise false
  381. */
  382. public boolean contains(Point p) {
  383. return CellRendererPane.this.contains(p);
  384. }
  385. /**
  386. * Returns the location of the object on the screen.
  387. *
  388. * @return location of object on screen -- can be null if this object
  389. * is not on the screen
  390. */
  391. public Point getLocationOnScreen() {
  392. return CellRendererPane.this.getLocationOnScreen();
  393. }
  394. /**
  395. * Gets the location of the object relative to the parent in the form
  396. * of a point specifying the object's top-left corner in the screen's
  397. * coordinate space.
  398. *
  399. * @return An instance of Point representing the top-left corner of
  400. * the objects's bounds in the coordinate space of the screen; null if
  401. * this object or its parent are not on the screen
  402. */
  403. public Point getLocation() {
  404. return CellRendererPane.this.getLocation();
  405. }
  406. /**
  407. * Sets the location of the object relative to the parent.
  408. */
  409. public void setLocation(Point p) {
  410. CellRendererPane.this.setLocation(p);
  411. }
  412. /**
  413. * Gets the bounds of this object in the form of a Rectangle object.
  414. * The bounds specify this object's width, height, and location
  415. * relative to its parent.
  416. *
  417. * @return A rectangle indicating this component's bounds; null if
  418. * this object is not on the screen.
  419. */
  420. public Rectangle getBounds() {
  421. return CellRendererPane.this.getBounds();
  422. }
  423. /**
  424. * Sets the bounds of this object in the form of a Rectangle object.
  425. * The bounds specify this object's width, height, and location
  426. * relative to its parent.
  427. *
  428. * @param A rectangle indicating this component's bounds
  429. */
  430. public void setBounds(Rectangle r) {
  431. CellRendererPane.this.setBounds(r);
  432. }
  433. /**
  434. * Returns the size of this object in the form of a Dimension object.
  435. * The height field of the Dimension object contains this objects's
  436. * height, and the width field of the Dimension object contains this
  437. * object's width.
  438. *
  439. * @return A Dimension object that indicates the size of this
  440. * component; null if this object is not on the screen
  441. */
  442. public Dimension getSize() {
  443. return CellRendererPane.this.getSize();
  444. }
  445. /**
  446. * Resizes this object so that it has width width and height.
  447. *
  448. * @param d - The dimension specifying the new size of the object.
  449. */
  450. public void setSize(Dimension d) {
  451. CellRendererPane.this.setSize(d);
  452. }
  453. /**
  454. * Returns the Accessible child, if one exists, contained at the local
  455. * coordinate Point.
  456. *
  457. * @param p The point defining the top-left corner of the Accessible,
  458. * given in the coordinate space of the object's parent.
  459. * @return the Accessible, if it exists, at the specified location;
  460. * else null
  461. */
  462. public Accessible getAccessibleAt(Point p) {
  463. return SwingUtilities.getAccessibleAt(CellRendererPane.this,p);
  464. }
  465. /**
  466. * Returns whether this object can accept focus or not.
  467. *
  468. * @return true if object can accept focus; otherwise false
  469. */
  470. public boolean isFocusTraversable() {
  471. return CellRendererPane.this.isFocusTraversable();
  472. }
  473. /**
  474. * Requests focus for this object.
  475. */
  476. public void requestFocus() {
  477. CellRendererPane.this.requestFocus();
  478. }
  479. /**
  480. * Adds the specified focus listener to receive focus events from this
  481. * component.
  482. *
  483. * @param l the focus listener
  484. */
  485. public void addFocusListener(FocusListener l) {
  486. CellRendererPane.this.addFocusListener(l);
  487. }
  488. /**
  489. * Removes the specified focus listener so it no longer receives focus
  490. * events from this component.
  491. *
  492. * @param l the focus listener
  493. */
  494. public void removeFocusListener(FocusListener l) {
  495. CellRendererPane.this.removeFocusListener(l);
  496. }
  497. } // inner class AccessibleCellRendererPane
  498. }