Replacing RepaintManager with RepaintController which does not reference Applet in its signatures
1.1 --- a/build.xml Fri Jun 19 21:46:14 2009 +0200
1.2 +++ b/build.xml Sat Jun 20 22:10:34 2009 +0200
1.3 @@ -4,7 +4,9 @@
1.4
1.5 <target name="all">
1.6 <antcall target="base"/>
1.7 + <antcall target="applet"/>
1.8 <antcall target="corba"/>
1.9 + <antcall target="deprecated7"/>
1.10 </target>
1.11
1.12 <!-- basic parameters -->
1.13 @@ -125,7 +127,14 @@
1.14
1.15 <selector id="deprecated7">
1.16 <or>
1.17 + <!-- deprecated as it contains one method
1.18 + that references Applet
1.19 + -->
1.20 <filename name="java/beans/Beans*"/>
1.21 + <!-- deprecated as it contains one method
1.22 + that references Applet
1.23 + -->
1.24 + <filename name="javax/swing/RepaintManager*"/>
1.25
1.26 <!-- tools -->
1.27 <filename name="sun/tools/serialver/**"/>
1.28 @@ -184,7 +193,7 @@
1.29 <target name="corba">
1.30 <antcall target="-compile-one-module">
1.31 <param name="module" value="corba"/>
1.32 - <param name="depends" value="base"/>
1.33 + <param name="depends" value="base:applet"/>
1.34 </antcall>
1.35 </target>
1.36
2.1 --- a/src/share/classes/com/sun/java/swing/SwingUtilities3.java Fri Jun 19 21:46:14 2009 +0200
2.2 +++ b/src/share/classes/com/sun/java/swing/SwingUtilities3.java Sat Jun 20 22:10:34 2009 +0200
2.3 @@ -33,7 +33,7 @@
2.4 import java.awt.EventQueue;
2.5 import java.awt.Component;
2.6 import javax.swing.JComponent;
2.7 -import javax.swing.RepaintManager;
2.8 +import javax.swing.RepaintController;
2.9
2.10 /**
2.11 * A collection of utility methods for Swing.
2.12 @@ -49,32 +49,32 @@
2.13 */
2.14 public class SwingUtilities3 {
2.15 /**
2.16 - * The {@code clientProperty} key for delegate {@code RepaintManager}
2.17 + * The {@code clientProperty} key for delegate {@code RepaintController}
2.18 */
2.19 private static final Object DELEGATE_REPAINT_MANAGER_KEY =
2.20 - new StringBuilder("DelegateRepaintManagerKey");
2.21 + new StringBuilder("DelegateRepaintControllerKey");
2.22
2.23 /**
2.24 - * Registers delegate RepaintManager for {@code JComponent}.
2.25 + * Registers delegate RepaintController for {@code JComponent}.
2.26 */
2.27 - public static void setDelegateRepaintManager(JComponent component,
2.28 - RepaintManager repaintManager) {
2.29 + public static void setDelegateRepaintController(JComponent component,
2.30 + RepaintController RepaintController) {
2.31 /* setting up flag in AppContext to speed up lookups in case
2.32 - * there are no delegate RepaintManagers used.
2.33 + * there are no delegate RepaintControllers used.
2.34 */
2.35 AppContext.getAppContext().put(DELEGATE_REPAINT_MANAGER_KEY,
2.36 Boolean.TRUE);
2.37
2.38 component.putClientProperty(DELEGATE_REPAINT_MANAGER_KEY,
2.39 - repaintManager);
2.40 + RepaintController);
2.41 }
2.42
2.43 /**
2.44 - * Returns delegate {@code RepaintManager} for {@code component} hierarchy.
2.45 + * Returns delegate {@code RepaintController} for {@code component} hierarchy.
2.46 */
2.47 - public static RepaintManager getDelegateRepaintManager(Component
2.48 + public static RepaintController getDelegateRepaintController(Component
2.49 component) {
2.50 - RepaintManager delegate = null;
2.51 + RepaintController delegate = null;
2.52 if (Boolean.TRUE == AppContext.getAppContext().get(
2.53 DELEGATE_REPAINT_MANAGER_KEY)) {
2.54 while (delegate == null && component != null) {
2.55 @@ -83,7 +83,7 @@
2.56 component = component.getParent();
2.57 }
2.58 if (component != null) {
2.59 - delegate = (RepaintManager)
2.60 + delegate = (RepaintController)
2.61 ((JComponent) component)
2.62 .getClientProperty(DELEGATE_REPAINT_MANAGER_KEY);
2.63 component = component.getParent();
3.1 --- a/src/share/classes/javax/swing/BufferStrategyPaintManager.java Fri Jun 19 21:46:14 2009 +0200
3.2 +++ b/src/share/classes/javax/swing/BufferStrategyPaintManager.java Sat Jun 20 22:10:34 2009 +0200
3.3 @@ -43,7 +43,7 @@
3.4 *
3.5 * @author Scott Violet
3.6 */
3.7 -class BufferStrategyPaintManager extends RepaintManager.PaintManager {
3.8 +class BufferStrategyPaintManager extends RepaintController.PaintManager {
3.9 //
3.10 // All drawing is done to a BufferStrategy. At the end of painting
3.11 // (endPaint) the region that was painted is flushed to the screen
3.12 @@ -633,7 +633,7 @@
3.13 if (bufferInfos != null) {
3.14 dispose(bufferInfos);
3.15 bufferInfos = null;
3.16 - repaintManager.setPaintManager(null);
3.17 + RepaintController.setPaintManager(null);
3.18 }
3.19 }
3.20
4.1 --- a/src/share/classes/javax/swing/DebugGraphics.java Fri Jun 19 21:46:14 2009 +0200
4.2 +++ b/src/share/classes/javax/swing/DebugGraphics.java Sat Jun 20 22:10:34 2009 +0200
4.3 @@ -37,12 +37,12 @@
4.4 * method.
4.5 * <p>
4.6 * NOTE: You must turn off double buffering to use DebugGraphics:
4.7 - * RepaintManager repaintManager = RepaintManager.currentManager(component);
4.8 - * repaintManager.setDoubleBufferingEnabled(false);
4.9 + * RepaintController RepaintController = RepaintController.currentManager(component);
4.10 + * RepaintController.setDoubleBufferingEnabled(false);
4.11 *
4.12 * @see JComponent#setDebugGraphicsOptions
4.13 - * @see RepaintManager#currentManager
4.14 - * @see RepaintManager#setDoubleBufferingEnabled
4.15 + * @see RepaintController#currentManager
4.16 + * @see RepaintController#setDoubleBufferingEnabled
4.17 *
4.18 * @author Dave Karlton
4.19 */
5.1 --- a/src/share/classes/javax/swing/DefaultDesktopManager.java Fri Jun 19 21:46:14 2009 +0200
5.2 +++ b/src/share/classes/javax/swing/DefaultDesktopManager.java Sat Jun 20 22:10:34 2009 +0200
5.3 @@ -640,7 +640,7 @@
5.4 JComponent parent = (JComponent)f.getParent();
5.5 Rectangle visBounds = previousBounds.intersection(desktopBounds);
5.6
5.7 - RepaintManager currentManager = RepaintManager.currentManager(f);
5.8 + RepaintController currentManager = RepaintController.currentManager(f);
5.9
5.10 currentManager.beginPaint();
5.11 try {
6.1 --- a/src/share/classes/javax/swing/JApplet.java Fri Jun 19 21:46:14 2009 +0200
6.2 +++ b/src/share/classes/javax/swing/JApplet.java Sat Jun 20 22:10:34 2009 +0200
6.3 @@ -492,7 +492,7 @@
6.4
6.5 /**
6.6 * Repaints the specified rectangle of this component within
6.7 - * <code>time</code> milliseconds. Refer to <code>RepaintManager</code>
6.8 + * <code>time</code> milliseconds. Refer to <code>RepaintController</code>
6.9 * for details on how the repaint is handled.
6.10 *
6.11 * @param time maximum time in milliseconds before update
6.12 @@ -500,12 +500,12 @@
6.13 * @param y the <i>y</i> coordinate
6.14 * @param width the width
6.15 * @param height the height
6.16 - * @see RepaintManager
6.17 + * @see RepaintController
6.18 * @since 1.6
6.19 */
6.20 public void repaint(long time, int x, int y, int width, int height) {
6.21 - if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {
6.22 - RepaintManager.currentManager(this).addDirtyRegion(
6.23 + if (RepaintController.HANDLE_TOP_LEVEL_PAINT) {
6.24 + RepaintController.currentManager(this).addDirtyRegion0(
6.25 this, x, y, width, height);
6.26 }
6.27 else {
7.1 --- a/src/share/classes/javax/swing/JComponent.java Fri Jun 19 21:46:14 2009 +0200
7.2 +++ b/src/share/classes/javax/swing/JComponent.java Sat Jun 20 22:10:34 2009 +0200
7.3 @@ -987,7 +987,7 @@
7.4 Graphics componentGraphics = getComponentGraphics(g);
7.5 Graphics co = componentGraphics.create();
7.6 try {
7.7 - RepaintManager repaintManager = RepaintManager.currentManager(this);
7.8 + RepaintController repaintManager = RepaintController.currentManager(this);
7.9 Rectangle clipRect = co.getClipBounds();
7.10 int clipX;
7.11 int clipY;
7.12 @@ -1067,10 +1067,10 @@
7.13
7.14 // paint forcing use of the double buffer. This is used for historical
7.15 // reasons: JViewport, when scrolling, previously directly invoked paint
7.16 - // while turning off double buffering at the RepaintManager level, this
7.17 + // while turning off double buffering at the RepaintController level, this
7.18 // codes simulates that.
7.19 void paintForceDoubleBuffered(Graphics g) {
7.20 - RepaintManager rm = RepaintManager.currentManager(this);
7.21 + RepaintController rm = RepaintController.currentManager(this);
7.22 Rectangle clip = g.getClipBounds();
7.23 rm.beginPaint();
7.24 setFlag(IS_REPAINTING, true);
7.25 @@ -3334,7 +3334,7 @@
7.26 }
7.27
7.28 /**
7.29 - * This is invoked by the <code>RepaintManager</code> if
7.30 + * This is invoked by the <code>RepaintController</code> if
7.31 * <code>createImage</code> is called on the component.
7.32 *
7.33 * @param newValue true if the double buffer image was created from this component
7.34 @@ -3344,7 +3344,7 @@
7.35 }
7.36
7.37 /**
7.38 - * Returns true if the <code>RepaintManager</code>
7.39 + * Returns true if the <code>RepaintController</code>
7.40 * created the double buffer image from the component.
7.41 *
7.42 * @return true if this component had a double buffer image, false otherwise
7.43 @@ -4752,7 +4752,7 @@
7.44 deregisterNextFocusableComponent();
7.45
7.46 if (getCreatedDoubleBuffer()) {
7.47 - RepaintManager.currentManager(this).resetDoubleBuffer();
7.48 + RepaintController.currentManager(this).resetDoubleBuffer();
7.49 setCreatedDoubleBuffer(false);
7.50 }
7.51 if (autoscrolls) {
7.52 @@ -4772,10 +4772,10 @@
7.53 * @param width the width of the dirty region
7.54 * @param height the height of the dirty region
7.55 * @see java.awt.Component#isShowing
7.56 - * @see RepaintManager#addDirtyRegion
7.57 + * @see RepaintController#addDirtyRegion
7.58 */
7.59 public void repaint(long tm, int x, int y, int width, int height) {
7.60 - RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
7.61 + RepaintController.currentManager(this).addDirtyRegion(this, x, y, width, height);
7.62 }
7.63
7.64
7.65 @@ -4786,7 +4786,7 @@
7.66 *
7.67 * @param r a <code>Rectangle</code> containing the dirty region
7.68 * @see java.awt.Component#isShowing
7.69 - * @see RepaintManager#addDirtyRegion
7.70 + * @see RepaintController#addDirtyRegion
7.71 */
7.72 public void repaint(Rectangle r) {
7.73 repaint(0,r.x,r.y,r.width,r.height);
7.74 @@ -4817,7 +4817,7 @@
7.75 * @see java.awt.Component#invalidate
7.76 * @see java.awt.Container#validate
7.77 * @see #isValidateRoot
7.78 - * @see RepaintManager#addInvalidComponent
7.79 + * @see RepaintController#addInvalidComponent
7.80 */
7.81 public void revalidate() {
7.82 if (getParent() == null) {
7.83 @@ -4831,7 +4831,7 @@
7.84 }
7.85 if (SwingUtilities.isEventDispatchThread()) {
7.86 invalidate();
7.87 - RepaintManager.currentManager(this).addInvalidComponent(this);
7.88 + RepaintController.currentManager(this).addInvalidComponent(this);
7.89 }
7.90 else {
7.91 // To avoid a flood of Runnables when constructing GUIs off
7.92 @@ -4980,7 +4980,7 @@
7.93 JComponent bufferedComponent = null;
7.94 JComponent paintingComponent = this;
7.95
7.96 - RepaintManager repaintManager = RepaintManager.currentManager(this);
7.97 + RepaintController repaintManager = RepaintController.currentManager(this);
7.98 // parent Container's up to Window or Applet. First container is
7.99 // the direct parent. Note that in testing it was faster to
7.100 // alloc a new Vector vs keeping a stack of them around, and gc
7.101 @@ -5121,7 +5121,7 @@
7.102 g = safelyGetGraphics(paintingComponent, c);
7.103 try {
7.104 if (hasBuffer) {
7.105 - RepaintManager rm = RepaintManager.currentManager(
7.106 + RepaintController rm = RepaintController.currentManager(
7.107 bufferedComponent);
7.108 rm.beginPaint();
7.109 try {
7.110 @@ -5163,7 +5163,7 @@
7.111 /**
7.112 * Paints to the specified graphics. This does not set the clip and it
7.113 * does not adjust the Graphics in anyway, callers must do that first.
7.114 - * This method is package-private for RepaintManager.PaintManager and
7.115 + * This method is package-private for RepaintController.PaintManager and
7.116 * its subclasses to call, it is NOT intended for general use outside
7.117 * of that.
7.118 */
7.119 @@ -5175,7 +5175,7 @@
7.120 setFlag(IS_PAINTING_TILE, true);
7.121 }
7.122 if (getFlag(IS_REPAINTING)) {
7.123 - // Called from paintImmediately (RepaintManager) to fill
7.124 + // Called from paintImmediately (RepaintController) to fill
7.125 // repaint request
7.126 paint(g);
7.127 } else {
8.1 --- a/src/share/classes/javax/swing/JDialog.java Fri Jun 19 21:46:14 2009 +0200
8.2 +++ b/src/share/classes/javax/swing/JDialog.java Sat Jun 20 22:10:34 2009 +0200
8.3 @@ -1084,7 +1084,7 @@
8.4
8.5 /**
8.6 * Repaints the specified rectangle of this component within
8.7 - * <code>time</code> milliseconds. Refer to <code>RepaintManager</code>
8.8 + * <code>time</code> milliseconds. Refer to <code>RepaintController</code>
8.9 * for details on how the repaint is handled.
8.10 *
8.11 * @param time maximum time in milliseconds before update
8.12 @@ -1092,12 +1092,12 @@
8.13 * @param y the <i>y</i> coordinate
8.14 * @param width the width
8.15 * @param height the height
8.16 - * @see RepaintManager
8.17 + * @see RepaintController
8.18 * @since 1.6
8.19 */
8.20 public void repaint(long time, int x, int y, int width, int height) {
8.21 - if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {
8.22 - RepaintManager.currentManager(this).addDirtyRegion(
8.23 + if (RepaintController.HANDLE_TOP_LEVEL_PAINT) {
8.24 + RepaintController.currentManager(this).addDirtyRegion(
8.25 this, x, y, width, height);
8.26 }
8.27 else {
9.1 --- a/src/share/classes/javax/swing/JFrame.java Fri Jun 19 21:46:14 2009 +0200
9.2 +++ b/src/share/classes/javax/swing/JFrame.java Sat Jun 20 22:10:34 2009 +0200
9.3 @@ -761,7 +761,7 @@
9.4
9.5 /**
9.6 * Repaints the specified rectangle of this component within
9.7 - * <code>time</code> milliseconds. Refer to <code>RepaintManager</code>
9.8 + * <code>time</code> milliseconds. Refer to <code>RepaintController</code>
9.9 * for details on how the repaint is handled.
9.10 *
9.11 * @param time maximum time in milliseconds before update
9.12 @@ -769,12 +769,12 @@
9.13 * @param y the <i>y</i> coordinate
9.14 * @param width the width
9.15 * @param height the height
9.16 - * @see RepaintManager
9.17 + * @see RepaintController
9.18 * @since 1.6
9.19 */
9.20 public void repaint(long time, int x, int y, int width, int height) {
9.21 - if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {
9.22 - RepaintManager.currentManager(this).addDirtyRegion(
9.23 + if (RepaintController.HANDLE_TOP_LEVEL_PAINT) {
9.24 + RepaintController.currentManager(this).addDirtyRegion(
9.25 this, x, y, width, height);
9.26 }
9.27 else {
10.1 --- a/src/share/classes/javax/swing/JRootPane.java Fri Jun 19 21:46:14 2009 +0200
10.2 +++ b/src/share/classes/javax/swing/JRootPane.java Sat Jun 20 22:10:34 2009 +0200
10.3 @@ -376,7 +376,7 @@
10.4 public void setDoubleBuffered(boolean aFlag) {
10.5 if (isDoubleBuffered() != aFlag) {
10.6 super.setDoubleBuffered(aFlag);
10.7 - RepaintManager.currentManager(this).doubleBufferingChanged(this);
10.8 + RepaintController.currentManager(this).doubleBufferingChanged(this);
10.9 }
10.10 }
10.11
10.12 @@ -825,7 +825,7 @@
10.13 Thread.dumpStack();
10.14 }
10.15 useTrueDoubleBuffering = false;
10.16 - RepaintManager.currentManager(this).
10.17 + RepaintController.currentManager(this).
10.18 doubleBufferingChanged(this);
10.19 }
10.20 }
11.1 --- a/src/share/classes/javax/swing/JViewport.java Fri Jun 19 21:46:14 2009 +0200
11.2 +++ b/src/share/classes/javax/swing/JViewport.java Sat Jun 20 22:10:34 2009 +0200
11.3 @@ -464,7 +464,7 @@
11.4 * <code>true</code> to <code>isValidateRoot</code>.
11.5 * If all the <code>Component</code>'s parents are visible,
11.6 * <code>validate</code> will then be invoked on it. The
11.7 - * <code>RepaintManager</code> is then invoked with
11.8 + * <code>RepaintController</code> is then invoked with
11.9 * <code>removeInvalidComponent</code>. This
11.10 * is the synchronous version of a <code>revalidate</code>.
11.11 */
11.12 @@ -515,9 +515,9 @@
11.13 // Validate the root.
11.14 validateRoot.validate();
11.15
11.16 - // And let the RepaintManager it does not have to validate from
11.17 + // And let the RepaintController it does not have to validate from
11.18 // validateRoot anymore.
11.19 - RepaintManager rm = RepaintManager.currentManager(this);
11.20 + RepaintController rm = RepaintController.currentManager(this);
11.21
11.22 if (rm != null) {
11.23 rm.removeInvalidComponent((JComponent)validateRoot);
11.24 @@ -1111,7 +1111,7 @@
11.25
11.26 if ((oldX != newX) || (oldY != newY)) {
11.27 if (!waitingForRepaint && isBlitting() && canUseWindowBlitter()) {
11.28 - RepaintManager rm = RepaintManager.currentManager(this);
11.29 + RepaintController rm = RepaintController.currentManager(this);
11.30 // The cast to JComponent will work, if view is not
11.31 // a JComponent, isBlitting will return false.
11.32 JComponent jview = (JComponent)view;
11.33 @@ -1399,7 +1399,7 @@
11.34
11.35 /**
11.36 * Always repaint in the parents coordinate system to make sure
11.37 - * only one paint is performed by the <code>RepaintManager</code>.
11.38 + * only one paint is performed by the <code>RepaintController</code>.
11.39 *
11.40 * @param tm maximum time in milliseconds before update
11.41 * @param x the <code>x</code> coordinate (pixels over from left)
11.42 @@ -1551,7 +1551,7 @@
11.43 }
11.44
11.45 boolean retValue;
11.46 - RepaintManager rm = RepaintManager.currentManager(this);
11.47 + RepaintController rm = RepaintController.currentManager(this);
11.48 JComponent view = (JComponent) getView();
11.49
11.50 if (lastPaintPosition == null ||
11.51 @@ -1607,7 +1607,7 @@
11.52 // blitFrom/blitTo are in JViewport coordinates system
11.53 // not the views coordinate space.
11.54 // clip* are in the views coordinate space.
11.55 - RepaintManager rm = RepaintManager.currentManager(this);
11.56 + RepaintController rm = RepaintController.currentManager(this);
11.57 int bdx = blitToX - blitFromX;
11.58 int bdy = blitToY - blitFromY;
11.59
11.60 @@ -1676,7 +1676,7 @@
11.61 return false;
11.62 }
11.63
11.64 - Rectangle dirtyRegion = RepaintManager.currentManager(this).
11.65 + Rectangle dirtyRegion = RepaintController.currentManager(this).
11.66 getDirtyRegion((JComponent)getParent());
11.67
11.68 if (dirtyRegion != null && dirtyRegion.width > 0 &&
12.1 --- a/src/share/classes/javax/swing/JWindow.java Fri Jun 19 21:46:14 2009 +0200
12.2 +++ b/src/share/classes/javax/swing/JWindow.java Sat Jun 20 22:10:34 2009 +0200
12.3 @@ -593,7 +593,7 @@
12.4
12.5 /**
12.6 * Repaints the specified rectangle of this component within
12.7 - * <code>time</code> milliseconds. Refer to <code>RepaintManager</code>
12.8 + * <code>time</code> milliseconds. Refer to <code>RepaintController</code>
12.9 * for details on how the repaint is handled.
12.10 *
12.11 * @param time maximum time in milliseconds before update
12.12 @@ -601,12 +601,12 @@
12.13 * @param y the <i>y</i> coordinate
12.14 * @param width the width
12.15 * @param height the height
12.16 - * @see RepaintManager
12.17 + * @see RepaintController
12.18 * @since 1.6
12.19 */
12.20 public void repaint(long time, int x, int y, int width, int height) {
12.21 - if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {
12.22 - RepaintManager.currentManager(this).addDirtyRegion(
12.23 + if (RepaintController.HANDLE_TOP_LEVEL_PAINT) {
12.24 + RepaintController.currentManager(this).addDirtyRegion(
12.25 this, x, y, width, height);
12.26 }
12.27 else {
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/src/share/classes/javax/swing/RepaintController.java Sat Jun 20 22:10:34 2009 +0200
13.3 @@ -0,0 +1,1647 @@
13.4 +/*
13.5 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13.7 + *
13.8 + * This code is free software; you can redistribute it and/or modify it
13.9 + * under the terms of the GNU General Public License version 2 only, as
13.10 + * published by the Free Software Foundation. Sun designates this
13.11 + * particular file as subject to the "Classpath" exception as provided
13.12 + * by Sun in the LICENSE file that accompanied this code.
13.13 + *
13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13.17 + * version 2 for more details (a copy is included in the LICENSE file that
13.18 + * accompanied this code).
13.19 + *
13.20 + * You should have received a copy of the GNU General Public License version
13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13.23 + *
13.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
13.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
13.26 + * have any questions.
13.27 + */
13.28 +package javax.swing;
13.29 +
13.30 +
13.31 +import java.awt.*;
13.32 +import java.awt.event.*;
13.33 +import java.awt.image.VolatileImage;
13.34 +import java.security.AccessController;
13.35 +import java.util.*;
13.36 +
13.37 +import sun.awt.AWTAccessor;
13.38 +import sun.awt.AppContext;
13.39 +import sun.awt.DisplayChangedListener;
13.40 +import sun.awt.SunToolkit;
13.41 +import sun.java2d.SunGraphicsEnvironment;
13.42 +import sun.security.action.GetPropertyAction;
13.43 +
13.44 +import com.sun.java.swing.SwingUtilities3;
13.45 +import sun.swing.SwingUtilities2;
13.46 +
13.47 +/**
13.48 + * This class manages repaint requests, allowing the number
13.49 + * of repaints to be minimized, for example by collapsing multiple
13.50 + * requests into a single repaint for members of a component tree.
13.51 + * <p>
13.52 + * As of 1.6 <code>RepaintController</code> handles repaint requests
13.53 + * for Swing's top level components (<code>JApplet</code>,
13.54 + * <code>JWindow</code>, <code>JFrame</code> and <code>JDialog</code>).
13.55 + * Any calls to <code>repaint</code> on one of these will call into the
13.56 + * appropriate <code>addDirtyRegion</code> method.
13.57 + *
13.58 + * @author Arnaud Weber
13.59 + */
13.60 +public class RepaintController
13.61 +{
13.62 + /**
13.63 + * Whether or not the RepaintController should handle paint requests
13.64 + * for top levels.
13.65 + */
13.66 + static final boolean HANDLE_TOP_LEVEL_PAINT;
13.67 +
13.68 + private static final short BUFFER_STRATEGY_NOT_SPECIFIED = 0;
13.69 + private static final short BUFFER_STRATEGY_SPECIFIED_ON = 1;
13.70 + private static final short BUFFER_STRATEGY_SPECIFIED_OFF = 2;
13.71 +
13.72 + private static final short BUFFER_STRATEGY_TYPE;
13.73 +
13.74 + /**
13.75 + * Maps from GraphicsConfiguration to VolatileImage.
13.76 + */
13.77 + private Map<GraphicsConfiguration,VolatileImage> volatileMap = new
13.78 + HashMap<GraphicsConfiguration,VolatileImage>(1);
13.79 +
13.80 + //
13.81 + // As of 1.6 Swing handles scheduling of paint events from native code.
13.82 + // That is, SwingPaintEventDispatcher is invoked on the toolkit thread,
13.83 + // which in turn invokes nativeAddDirtyRegion. Because this is invoked
13.84 + // from the native thread we can not invoke any public methods and so
13.85 + // we introduce these added maps. So, any time nativeAddDirtyRegion is
13.86 + // invoked the region is added to hwDirtyComponents and a work request
13.87 + // is scheduled. When the work request is processed all entries in
13.88 + // this map are pushed to the real map (dirtyComponents) and then
13.89 + // painted with the rest of the components.
13.90 + //
13.91 + private Map<Container,Rectangle> hwDirtyComponents;
13.92 +
13.93 + private Map<Component,Rectangle> dirtyComponents;
13.94 + private Map<Component,Rectangle> tmpDirtyComponents;
13.95 + private java.util.List<Component> invalidComponents;
13.96 +
13.97 + // List of Runnables that need to be processed before painting from AWT.
13.98 + private java.util.List<Runnable> runnableList;
13.99 +
13.100 + boolean doubleBufferingEnabled = true;
13.101 +
13.102 + private Dimension doubleBufferMaxSize;
13.103 +
13.104 + // Support for both the standard and volatile offscreen buffers exists to
13.105 + // provide backwards compatibility for the [rare] programs which may be
13.106 + // calling getOffScreenBuffer() and not expecting to get a VolatileImage.
13.107 + // Swing internally is migrating to use *only* the volatile image buffer.
13.108 +
13.109 + // Support for standard offscreen buffer
13.110 + //
13.111 + DoubleBufferInfo standardDoubleBuffer;
13.112 +
13.113 + /**
13.114 + * Object responsible for hanlding core paint functionality.
13.115 + */
13.116 + private PaintManager paintManager;
13.117 +
13.118 + private static final Object RepaintControllerKey = RepaintController.class;
13.119 +
13.120 + // Whether or not a VolatileImage should be used for double-buffered painting
13.121 + static boolean volatileImageBufferEnabled = true;
13.122 + /**
13.123 + * Value of the system property awt.nativeDoubleBuffering.
13.124 + */
13.125 + private static boolean nativeDoubleBuffering;
13.126 +
13.127 + // The maximum number of times Swing will attempt to use the VolatileImage
13.128 + // buffer during a paint operation.
13.129 + private static final int VOLATILE_LOOP_MAX = 2;
13.130 +
13.131 + /**
13.132 + * Number of <code>beginPaint</code> that have been invoked.
13.133 + */
13.134 + private int paintDepth = 0;
13.135 +
13.136 + /**
13.137 + * Type of buffer strategy to use. Will be one of the BUFFER_STRATEGY_
13.138 + * constants.
13.139 + */
13.140 + private short bufferStrategyType;
13.141 +
13.142 + //
13.143 + // BufferStrategyPaintManager has the unique characteristic that it
13.144 + // must deal with the buffer being lost while painting to it. For
13.145 + // example, if we paint a component and show it and the buffer has
13.146 + // become lost we must repaint the whole window. To deal with that
13.147 + // the PaintManager calls into repaintRoot, and if we're still in
13.148 + // the process of painting the repaintRoot field is set to the JRootPane
13.149 + // and after the current JComponent.paintImmediately call finishes
13.150 + // paintImmediately will be invoked on the repaintRoot. In this
13.151 + // way we don't try to show garbage to the screen.
13.152 + //
13.153 + /**
13.154 + * True if we're in the process of painting the dirty regions. This is
13.155 + * set to true in <code>paintDirtyRegions</code>.
13.156 + */
13.157 + private boolean painting;
13.158 + /**
13.159 + * If the PaintManager calls into repaintRoot during painting this field
13.160 + * will be set to the root.
13.161 + */
13.162 + private JComponent repaintRoot;
13.163 +
13.164 + /**
13.165 + * The Thread that has initiated painting. If null it
13.166 + * indicates painting is not currently in progress.
13.167 + */
13.168 + private Thread paintThread;
13.169 +
13.170 + /**
13.171 + * Runnable used to process all repaint/revalidate requests.
13.172 + */
13.173 + private final ProcessingRunnable processingRunnable;
13.174 +
13.175 +
13.176 + static {
13.177 + volatileImageBufferEnabled = "true".equals(AccessController.
13.178 + doPrivileged(new GetPropertyAction(
13.179 + "swing.volatileImageBufferEnabled", "true")));
13.180 + boolean headless = GraphicsEnvironment.isHeadless();
13.181 + if (volatileImageBufferEnabled && headless) {
13.182 + volatileImageBufferEnabled = false;
13.183 + }
13.184 + nativeDoubleBuffering = "true".equals(AccessController.doPrivileged(
13.185 + new GetPropertyAction("awt.nativeDoubleBuffering")));
13.186 + String bs = AccessController.doPrivileged(
13.187 + new GetPropertyAction("swing.bufferPerWindow"));
13.188 + if (headless) {
13.189 + BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
13.190 + }
13.191 + else if (bs == null) {
13.192 + BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_NOT_SPECIFIED;
13.193 + }
13.194 + else if ("true".equals(bs)) {
13.195 + BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_ON;
13.196 + }
13.197 + else {
13.198 + BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
13.199 + }
13.200 + HANDLE_TOP_LEVEL_PAINT = "true".equals(AccessController.doPrivileged(
13.201 + new GetPropertyAction("swing.handleTopLevelPaint", "true")));
13.202 + GraphicsEnvironment ge = GraphicsEnvironment.
13.203 + getLocalGraphicsEnvironment();
13.204 + if (ge instanceof SunGraphicsEnvironment) {
13.205 + ((SunGraphicsEnvironment)ge).addDisplayChangedListener(
13.206 + new DisplayChangedHandler());
13.207 + }
13.208 + }
13.209 +
13.210 + /**
13.211 + * Return the RepaintController for the calling thread given a Component.
13.212 + *
13.213 + * @param c a Component -- unused in the default implementation, but could
13.214 + * be used by an overridden version to return a different RepaintController
13.215 + * depending on the Component
13.216 + * @return the RepaintController object
13.217 + */
13.218 + public static RepaintController currentManager(Component c) {
13.219 + // Note: DisplayChangedRunnable passes in null as the component, so if
13.220 + // component is ever used to determine the current
13.221 + // RepaintController, DisplayChangedRunnable will need to be modified
13.222 + // accordingly.
13.223 + return currentManager(AppContext.getAppContext());
13.224 + }
13.225 +
13.226 + /**
13.227 + * Returns the RepaintController for the specified AppContext. If
13.228 + * a RepaintController has not been created for the specified
13.229 + * AppContext this will return null.
13.230 + */
13.231 + static RepaintController currentManager(AppContext appContext) {
13.232 + RepaintController rm = (RepaintController)appContext.get(RepaintControllerKey);
13.233 + if (rm == null) {
13.234 + rm = new RepaintController(BUFFER_STRATEGY_TYPE);
13.235 + appContext.put(RepaintControllerKey, rm);
13.236 + }
13.237 + return rm;
13.238 + }
13.239 +
13.240 + /**
13.241 + * Return the RepaintController for the calling thread given a JComponent.
13.242 + * <p>
13.243 + * Note: This method exists for backward binary compatibility with earlier
13.244 + * versions of the Swing library. It simply returns the result returned by
13.245 + * {@link #currentManager(Component)}.
13.246 + *
13.247 + * @param c a JComponent -- unused
13.248 + * @return the RepaintController object
13.249 + */
13.250 + public static RepaintController currentManager(JComponent c) {
13.251 + return currentManager((Component)c);
13.252 + }
13.253 +
13.254 +
13.255 + /**
13.256 + * Set the RepaintController that should be used for the calling
13.257 + * thread. <b>aRepaintController</b> will become the current RepaintController
13.258 + * for the calling thread's thread group.
13.259 + * @param aRepaintController the RepaintController object to use
13.260 + */
13.261 + public static void setCurrentManager(RepaintController aRepaintController) {
13.262 + if (aRepaintController != null) {
13.263 + SwingUtilities.appContextPut(RepaintControllerKey, aRepaintController);
13.264 + } else {
13.265 + SwingUtilities.appContextRemove(RepaintControllerKey);
13.266 + }
13.267 + }
13.268 +
13.269 + /**
13.270 + * Create a new RepaintController instance. You rarely call this constructor.
13.271 + * directly. To get the default RepaintController, use
13.272 + * RepaintController.currentManager(JComponent) (normally "this").
13.273 + */
13.274 + public RepaintController() {
13.275 + // Because we can't know what a subclass is doing with the
13.276 + // volatile image we immediately punt in subclasses. If this
13.277 + // poses a problem we'll need a more sophisticated detection algorithm,
13.278 + // or API.
13.279 + this(BUFFER_STRATEGY_SPECIFIED_OFF);
13.280 + }
13.281 +
13.282 + private RepaintController(short bufferStrategyType) {
13.283 + // If native doublebuffering is being used, do NOT use
13.284 + // Swing doublebuffering.
13.285 + doubleBufferingEnabled = !nativeDoubleBuffering;
13.286 + synchronized(this) {
13.287 + dirtyComponents = new IdentityHashMap<Component,Rectangle>();
13.288 + tmpDirtyComponents = new IdentityHashMap<Component,Rectangle>();
13.289 + this.bufferStrategyType = bufferStrategyType;
13.290 + hwDirtyComponents = new IdentityHashMap<Container,Rectangle>();
13.291 + }
13.292 + processingRunnable = new ProcessingRunnable();
13.293 + }
13.294 +
13.295 + private void displayChanged() {
13.296 + clearImages();
13.297 + }
13.298 +
13.299 + /**
13.300 + * Mark the component as in need of layout and queue a runnable
13.301 + * for the event dispatching thread that will validate the components
13.302 + * first isValidateRoot() ancestor.
13.303 + *
13.304 + * @see JComponent#isValidateRoot
13.305 + * @see #removeInvalidComponent
13.306 + */
13.307 + public synchronized void addInvalidComponent(JComponent invalidComponent)
13.308 + {
13.309 + RepaintController delegate = getDelegate(invalidComponent);
13.310 + if (delegate != null) {
13.311 + delegate.addInvalidComponent(invalidComponent);
13.312 + return;
13.313 + }
13.314 + Component validateRoot = null;
13.315 +
13.316 + /* Find the first JComponent ancestor of this component whose
13.317 + * isValidateRoot() method returns true.
13.318 + */
13.319 + for(Component c = invalidComponent; c != null; c = c.getParent()) {
13.320 + if ((c instanceof CellRendererPane) || (c.getPeer() == null)) {
13.321 + return;
13.322 + }
13.323 + if ((c instanceof JComponent) && (((JComponent)c).isValidateRoot())) {
13.324 + validateRoot = c;
13.325 + break;
13.326 + }
13.327 + }
13.328 +
13.329 + /* There's no validateRoot to apply validate to, so we're done.
13.330 + */
13.331 + if (validateRoot == null) {
13.332 + return;
13.333 + }
13.334 +
13.335 + /* If the validateRoot and all of its ancestors aren't visible
13.336 + * then we don't do anything. While we're walking up the tree
13.337 + * we find the root Window or Applet.
13.338 + */
13.339 + Component root = null;
13.340 +
13.341 + for(Component c = validateRoot; c != null; c = c.getParent()) {
13.342 + if (!c.isVisible() || (c.getPeer() == null)) {
13.343 + return;
13.344 + }
13.345 + if ((c instanceof Window) || SwingUtilities2.isApplet(c)) {
13.346 + root = c;
13.347 + break;
13.348 + }
13.349 + }
13.350 +
13.351 + if (root == null) {
13.352 + return;
13.353 + }
13.354 +
13.355 + /* Lazily create the invalidateComponents vector and add the
13.356 + * validateRoot if it's not there already. If this validateRoot
13.357 + * is already in the vector, we're done.
13.358 + */
13.359 + if (invalidComponents == null) {
13.360 + invalidComponents = new ArrayList<Component>();
13.361 + }
13.362 + else {
13.363 + int n = invalidComponents.size();
13.364 + for(int i = 0; i < n; i++) {
13.365 + if(validateRoot == invalidComponents.get(i)) {
13.366 + return;
13.367 + }
13.368 + }
13.369 + }
13.370 + invalidComponents.add(validateRoot);
13.371 +
13.372 + // Queue a Runnable to invoke paintDirtyRegions and
13.373 + // validateInvalidComponents.
13.374 + scheduleProcessingRunnable();
13.375 + }
13.376 +
13.377 +
13.378 + /**
13.379 + * Remove a component from the list of invalid components.
13.380 + *
13.381 + * @see #addInvalidComponent
13.382 + */
13.383 + public synchronized void removeInvalidComponent(JComponent component) {
13.384 + RepaintController delegate = getDelegate(component);
13.385 + if (delegate != null) {
13.386 + delegate.removeInvalidComponent(component);
13.387 + return;
13.388 + }
13.389 + if(invalidComponents != null) {
13.390 + int index = invalidComponents.indexOf(component);
13.391 + if(index != -1) {
13.392 + invalidComponents.remove(index);
13.393 + }
13.394 + }
13.395 + }
13.396 +
13.397 +
13.398 + /**
13.399 + * Add a component in the list of components that should be refreshed.
13.400 + * If <i>c</i> already has a dirty region, the rectangle <i>(x,y,w,h)</i>
13.401 + * will be unioned with the region that should be redrawn.
13.402 + *
13.403 + * @see JComponent#repaint
13.404 + */
13.405 + final void addDirtyRegion0(Container c, int x, int y, int w, int h) {
13.406 + /* Special cases we don't have to bother with.
13.407 + */
13.408 + if ((w <= 0) || (h <= 0) || (c == null)) {
13.409 + return;
13.410 + }
13.411 +
13.412 + if ((c.getWidth() <= 0) || (c.getHeight() <= 0)) {
13.413 + return;
13.414 + }
13.415 +
13.416 + if (extendDirtyRegion(c, x, y, w, h)) {
13.417 + // Component was already marked as dirty, region has been
13.418 + // extended, no need to continue.
13.419 + return;
13.420 + }
13.421 +
13.422 + /* Make sure that c and all it ancestors (up to an Applet or
13.423 + * Window) are visible. This loop has the same effect as
13.424 + * checking c.isShowing() (and note that it's still possible
13.425 + * that c is completely obscured by an opaque ancestor in
13.426 + * the specified rectangle).
13.427 + */
13.428 + Component root = null;
13.429 +
13.430 + // Note: We can't synchronize around this, Frame.getExtendedState
13.431 + // is synchronized so that if we were to synchronize around this
13.432 + // it could lead to the possibility of getting locks out
13.433 + // of order and deadlocking.
13.434 + for (Container p = c; p != null; p = p.getParent()) {
13.435 + if (!p.isVisible() || (p.getPeer() == null)) {
13.436 + return;
13.437 + }
13.438 + if ((p instanceof Window) || SwingUtilities2.isApplet(p)) {
13.439 + // Iconified frames are still visible!
13.440 + if (p instanceof Frame &&
13.441 + (((Frame)p).getExtendedState() & Frame.ICONIFIED) ==
13.442 + Frame.ICONIFIED) {
13.443 + return;
13.444 + }
13.445 + root = p;
13.446 + break;
13.447 + }
13.448 + }
13.449 +
13.450 + if (root == null) return;
13.451 +
13.452 + synchronized(this) {
13.453 + if (extendDirtyRegion(c, x, y, w, h)) {
13.454 + // In between last check and this check another thread
13.455 + // queued up runnable, can bail here.
13.456 + return;
13.457 + }
13.458 + dirtyComponents.put(c, new Rectangle(x, y, w, h));
13.459 + }
13.460 +
13.461 + // Queue a Runnable to invoke paintDirtyRegions and
13.462 + // validateInvalidComponents.
13.463 + scheduleProcessingRunnable();
13.464 + }
13.465 +
13.466 + /**
13.467 + * Add a component in the list of components that should be refreshed.
13.468 + * If <i>c</i> already has a dirty region, the rectangle <i>(x,y,w,h)</i>
13.469 + * will be unioned with the region that should be redrawn.
13.470 + *
13.471 + * @param c Component to repaint, null results in nothing happening.
13.472 + * @param x X coordinate of the region to repaint
13.473 + * @param y Y coordinate of the region to repaint
13.474 + * @param w Width of the region to repaint
13.475 + * @param h Height of the region to repaint
13.476 + * @see JComponent#repaint
13.477 + */
13.478 + public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
13.479 + {
13.480 + RepaintController delegate = getDelegate(c);
13.481 + if (delegate != null) {
13.482 + delegate.addDirtyRegion(c, x, y, w, h);
13.483 + return;
13.484 + }
13.485 + addDirtyRegion0(c, x, y, w, h);
13.486 + }
13.487 +
13.488 + /**
13.489 + * Adds <code>window</code> to the list of <code>Component</code>s that
13.490 + * need to be repainted.
13.491 + *
13.492 + * @param window Window to repaint, null results in nothing happening.
13.493 + * @param x X coordinate of the region to repaint
13.494 + * @param y Y coordinate of the region to repaint
13.495 + * @param w Width of the region to repaint
13.496 + * @param h Height of the region to repaint
13.497 + * @see JFrame#repaint
13.498 + * @see JWindow#repaint
13.499 + * @see JDialog#repaint
13.500 + * @since 1.6
13.501 + */
13.502 + public void addDirtyRegion(Window window, int x, int y, int w, int h) {
13.503 + addDirtyRegion0(window, x, y, w, h);
13.504 + }
13.505 +
13.506 + void scheduleHeavyWeightPaints() {
13.507 + Map<Container,Rectangle> hws;
13.508 +
13.509 + synchronized(this) {
13.510 + if (hwDirtyComponents.size() == 0) {
13.511 + return;
13.512 + }
13.513 + hws = hwDirtyComponents;
13.514 + hwDirtyComponents = new IdentityHashMap<Container,Rectangle>();
13.515 + }
13.516 + for (Container hw : hws.keySet()) {
13.517 + Rectangle dirty = hws.get(hw);
13.518 + if (hw instanceof Window) {
13.519 + addDirtyRegion((Window)hw, dirty.x, dirty.y,
13.520 + dirty.width, dirty.height);
13.521 + }
13.522 + else if (SwingUtilities2.isApplet(hw)) {
13.523 + addDirtyRegion0(hw, dirty.x, dirty.y,
13.524 + dirty.width, dirty.height);
13.525 + }
13.526 + else { // SwingHeavyWeight
13.527 + addDirtyRegion0(hw, dirty.x, dirty.y,
13.528 + dirty.width, dirty.height);
13.529 + }
13.530 + }
13.531 + }
13.532 +
13.533 + //
13.534 + // This is called from the toolkit thread when a native expose is
13.535 + // received.
13.536 + //
13.537 + void nativeAddDirtyRegion(AppContext appContext, Container c,
13.538 + int x, int y, int w, int h) {
13.539 + if (w > 0 && h > 0) {
13.540 + synchronized(this) {
13.541 + Rectangle dirty = hwDirtyComponents.get(c);
13.542 + if (dirty == null) {
13.543 + hwDirtyComponents.put(c, new Rectangle(x, y, w, h));
13.544 + }
13.545 + else {
13.546 + hwDirtyComponents.put(c, SwingUtilities.computeUnion(
13.547 + x, y, w, h, dirty));
13.548 + }
13.549 + }
13.550 + scheduleProcessingRunnable(appContext);
13.551 + }
13.552 + }
13.553 +
13.554 + //
13.555 + // This is called from the toolkit thread when awt needs to run a
13.556 + // Runnable before we paint.
13.557 + //
13.558 + void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c,
13.559 + Runnable r) {
13.560 + synchronized(this) {
13.561 + if (runnableList == null) {
13.562 + runnableList = new LinkedList<Runnable>();
13.563 + }
13.564 + runnableList.add(r);
13.565 + }
13.566 + scheduleProcessingRunnable(appContext);
13.567 + }
13.568 +
13.569 + /**
13.570 + * Extends the dirty region for the specified component to include
13.571 + * the new region.
13.572 + *
13.573 + * @return false if <code>c</code> is not yet marked dirty.
13.574 + */
13.575 + private synchronized boolean extendDirtyRegion(
13.576 + Component c, int x, int y, int w, int h) {
13.577 + Rectangle r = dirtyComponents.get(c);
13.578 + if (r != null) {
13.579 + // A non-null r implies c is already marked as dirty,
13.580 + // and that the parent is valid. Therefore we can
13.581 + // just union the rect and bail.
13.582 + SwingUtilities.computeUnion(x, y, w, h, r);
13.583 + return true;
13.584 + }
13.585 + return false;
13.586 + }
13.587 +
13.588 + /** Return the current dirty region for a component.
13.589 + * Return an empty rectangle if the component is not
13.590 + * dirty.
13.591 + */
13.592 + public Rectangle getDirtyRegion(JComponent aComponent) {
13.593 + RepaintController delegate = getDelegate(aComponent);
13.594 + if (delegate != null) {
13.595 + return delegate.getDirtyRegion(aComponent);
13.596 + }
13.597 + Rectangle r;
13.598 + synchronized(this) {
13.599 + r = dirtyComponents.get(aComponent);
13.600 + }
13.601 + if(r == null)
13.602 + return new Rectangle(0,0,0,0);
13.603 + else
13.604 + return new Rectangle(r);
13.605 + }
13.606 +
13.607 + /**
13.608 + * Mark a component completely dirty. <b>aComponent</b> will be
13.609 + * completely painted during the next paintDirtyRegions() call.
13.610 + */
13.611 + public void markCompletelyDirty(JComponent aComponent) {
13.612 + RepaintController delegate = getDelegate(aComponent);
13.613 + if (delegate != null) {
13.614 + delegate.markCompletelyDirty(aComponent);
13.615 + return;
13.616 + }
13.617 + addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE);
13.618 + }
13.619 +
13.620 + /**
13.621 + * Mark a component completely clean. <b>aComponent</b> will not
13.622 + * get painted during the next paintDirtyRegions() call.
13.623 + */
13.624 + public void markCompletelyClean(JComponent aComponent) {
13.625 + RepaintController delegate = getDelegate(aComponent);
13.626 + if (delegate != null) {
13.627 + delegate.markCompletelyClean(aComponent);
13.628 + return;
13.629 + }
13.630 + synchronized(this) {
13.631 + dirtyComponents.remove(aComponent);
13.632 + }
13.633 + }
13.634 +
13.635 + /**
13.636 + * Convenience method that returns true if <b>aComponent</b> will be completely
13.637 + * painted during the next paintDirtyRegions(). If computing dirty regions is
13.638 + * expensive for your component, use this method and avoid computing dirty region
13.639 + * if it return true.
13.640 + */
13.641 + public boolean isCompletelyDirty(JComponent aComponent) {
13.642 + RepaintController delegate = getDelegate(aComponent);
13.643 + if (delegate != null) {
13.644 + return delegate.isCompletelyDirty(aComponent);
13.645 + }
13.646 + Rectangle r;
13.647 +
13.648 + r = getDirtyRegion(aComponent);
13.649 + if(r.width == Integer.MAX_VALUE &&
13.650 + r.height == Integer.MAX_VALUE)
13.651 + return true;
13.652 + else
13.653 + return false;
13.654 + }
13.655 +
13.656 +
13.657 + /**
13.658 + * Validate all of the components that have been marked invalid.
13.659 + * @see #addInvalidComponent
13.660 + */
13.661 + public void validateInvalidComponents() {
13.662 + java.util.List<Component> ic;
13.663 + synchronized(this) {
13.664 + if(invalidComponents == null) {
13.665 + return;
13.666 + }
13.667 + ic = invalidComponents;
13.668 + invalidComponents = null;
13.669 + }
13.670 + int n = ic.size();
13.671 + for(int i = 0; i < n; i++) {
13.672 + ic.get(i).validate();
13.673 + }
13.674 + }
13.675 +
13.676 +
13.677 + /**
13.678 + * This is invoked to process paint requests. It's needed
13.679 + * for backward compatability in so far as RepaintController would previously
13.680 + * not see paint requests for top levels, so, we have to make sure
13.681 + * a subclass correctly paints any dirty top levels.
13.682 + */
13.683 + private void prePaintDirtyRegions() {
13.684 + Map<Component,Rectangle> dirtyComponents;
13.685 + java.util.List<Runnable> runnableList;
13.686 + synchronized(this) {
13.687 + dirtyComponents = this.dirtyComponents;
13.688 + runnableList = this.runnableList;
13.689 + this.runnableList = null;
13.690 + }
13.691 + if (runnableList != null) {
13.692 + for (Runnable runnable : runnableList) {
13.693 + runnable.run();
13.694 + }
13.695 + }
13.696 + paintDirtyRegions();
13.697 + if (dirtyComponents.size() > 0) {
13.698 + // This'll only happen if a subclass isn't correctly dealing
13.699 + // with toplevels.
13.700 + paintDirtyRegions(dirtyComponents);
13.701 + }
13.702 + }
13.703 +
13.704 + private void updateWindows(Map<Component,Rectangle> dirtyComponents) {
13.705 + Toolkit toolkit = Toolkit.getDefaultToolkit();
13.706 + if (!(toolkit instanceof SunToolkit &&
13.707 + ((SunToolkit)toolkit).needUpdateWindow()))
13.708 + {
13.709 + return;
13.710 + }
13.711 +
13.712 + Set<Window> windows = new HashSet<Window>();
13.713 + Set<Component> dirtyComps = dirtyComponents.keySet();
13.714 + for (Iterator<Component> it = dirtyComps.iterator(); it.hasNext();) {
13.715 + Component dirty = it.next();
13.716 + Window window = dirty instanceof Window ?
13.717 + (Window)dirty :
13.718 + SwingUtilities.getWindowAncestor(dirty);
13.719 + if (window != null &&
13.720 + !AWTAccessor.getWindowAccessor().isOpaque(window))
13.721 + {
13.722 + windows.add(window);
13.723 + }
13.724 + }
13.725 +
13.726 + for (Window window : windows) {
13.727 + AWTAccessor.getWindowAccessor().updateWindow(window);
13.728 + }
13.729 + }
13.730 +
13.731 + boolean isPainting() {
13.732 + return painting;
13.733 + }
13.734 +
13.735 + /**
13.736 + * Paint all of the components that have been marked dirty.
13.737 + *
13.738 + * @see #addDirtyRegion
13.739 + */
13.740 + public void paintDirtyRegions() {
13.741 + synchronized(this) { // swap for thread safety
13.742 + Map<Component,Rectangle> tmp = tmpDirtyComponents;
13.743 + tmpDirtyComponents = dirtyComponents;
13.744 + dirtyComponents = tmp;
13.745 + dirtyComponents.clear();
13.746 + }
13.747 + paintDirtyRegions(tmpDirtyComponents);
13.748 + }
13.749 +
13.750 + private void paintDirtyRegions(Map<Component,Rectangle>
13.751 + tmpDirtyComponents){
13.752 + int i, count;
13.753 + java.util.List<Component> roots;
13.754 + Component dirtyComponent;
13.755 +
13.756 + count = tmpDirtyComponents.size();
13.757 + if (count == 0) {
13.758 + return;
13.759 + }
13.760 +
13.761 + Rectangle rect;
13.762 + int localBoundsX = 0;
13.763 + int localBoundsY = 0;
13.764 + int localBoundsH;
13.765 + int localBoundsW;
13.766 + Enumeration keys;
13.767 +
13.768 + roots = new ArrayList<Component>(count);
13.769 +
13.770 + for (Component dirty : tmpDirtyComponents.keySet()) {
13.771 + collectDirtyComponents(tmpDirtyComponents, dirty, roots);
13.772 + }
13.773 +
13.774 + count = roots.size();
13.775 + painting = true;
13.776 + try {
13.777 + for(i=0 ; i < count ; i++) {
13.778 + dirtyComponent = roots.get(i);
13.779 + rect = tmpDirtyComponents.get(dirtyComponent);
13.780 + localBoundsH = dirtyComponent.getHeight();
13.781 + localBoundsW = dirtyComponent.getWidth();
13.782 +
13.783 + SwingUtilities.computeIntersection(localBoundsX,
13.784 + localBoundsY,
13.785 + localBoundsW,
13.786 + localBoundsH,
13.787 + rect);
13.788 + if (dirtyComponent instanceof JComponent) {
13.789 + ((JComponent)dirtyComponent).paintImmediately(
13.790 + rect.x,rect.y,rect.width, rect.height);
13.791 + }
13.792 + else if (dirtyComponent.isShowing()) {
13.793 + Graphics g = JComponent.safelyGetGraphics(
13.794 + dirtyComponent, dirtyComponent);
13.795 + // If the Graphics goes away, it means someone disposed of
13.796 + // the window, don't do anything.
13.797 + if (g != null) {
13.798 + g.setClip(rect.x, rect.y, rect.width, rect.height);
13.799 + try {
13.800 + dirtyComponent.paint(g);
13.801 + } finally {
13.802 + g.dispose();
13.803 + }
13.804 + }
13.805 + }
13.806 + // If the repaintRoot has been set, service it now and
13.807 + // remove any components that are children of repaintRoot.
13.808 + if (repaintRoot != null) {
13.809 + adjustRoots(repaintRoot, roots, i + 1);
13.810 + count = roots.size();
13.811 + paintManager.isRepaintingRoot = true;
13.812 + repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
13.813 + repaintRoot.getHeight());
13.814 + paintManager.isRepaintingRoot = false;
13.815 + // Only service repaintRoot once.
13.816 + repaintRoot = null;
13.817 + }
13.818 + }
13.819 + } finally {
13.820 + painting = false;
13.821 + }
13.822 +
13.823 + updateWindows(tmpDirtyComponents);
13.824 +
13.825 + tmpDirtyComponents.clear();
13.826 + }
13.827 +
13.828 +
13.829 + /**
13.830 + * Removes any components from roots that are children of
13.831 + * root.
13.832 + */
13.833 + private void adjustRoots(JComponent root,
13.834 + java.util.List<Component> roots, int index) {
13.835 + for (int i = roots.size() - 1; i >= index; i--) {
13.836 + Component c = roots.get(i);
13.837 + for(;;) {
13.838 + if (c == root || c == null || !(c instanceof JComponent)) {
13.839 + break;
13.840 + }
13.841 + c = c.getParent();
13.842 + }
13.843 + if (c == root) {
13.844 + roots.remove(i);
13.845 + }
13.846 + }
13.847 + }
13.848 +
13.849 + Rectangle tmp = new Rectangle();
13.850 +
13.851 + void collectDirtyComponents(Map<Component,Rectangle> dirtyComponents,
13.852 + Component dirtyComponent,
13.853 + java.util.List<Component> roots) {
13.854 + int dx, dy, rootDx, rootDy;
13.855 + Component component, rootDirtyComponent,parent;
13.856 + Rectangle cBounds;
13.857 +
13.858 + // Find the highest parent which is dirty. When we get out of this
13.859 + // rootDx and rootDy will contain the translation from the
13.860 + // rootDirtyComponent's coordinate system to the coordinates of the
13.861 + // original dirty component. The tmp Rect is also used to compute the
13.862 + // visible portion of the dirtyRect.
13.863 +
13.864 + component = rootDirtyComponent = dirtyComponent;
13.865 +
13.866 + int x = dirtyComponent.getX();
13.867 + int y = dirtyComponent.getY();
13.868 + int w = dirtyComponent.getWidth();
13.869 + int h = dirtyComponent.getHeight();
13.870 +
13.871 + dx = rootDx = 0;
13.872 + dy = rootDy = 0;
13.873 + tmp.setBounds(dirtyComponents.get(dirtyComponent));
13.874 +
13.875 + // System.out.println("Collect dirty component for bound " + tmp +
13.876 + // "component bounds is " + cBounds);;
13.877 + SwingUtilities.computeIntersection(0,0,w,h,tmp);
13.878 +
13.879 + if (tmp.isEmpty()) {
13.880 + // System.out.println("Empty 1");
13.881 + return;
13.882 + }
13.883 +
13.884 + for(;;) {
13.885 + if(!(component instanceof JComponent))
13.886 + break;
13.887 +
13.888 + parent = component.getParent();
13.889 + if(parent == null)
13.890 + break;
13.891 +
13.892 + component = parent;
13.893 +
13.894 + dx += x;
13.895 + dy += y;
13.896 + tmp.setLocation(tmp.x + x, tmp.y + y);
13.897 +
13.898 + x = component.getX();
13.899 + y = component.getY();
13.900 + w = component.getWidth();
13.901 + h = component.getHeight();
13.902 + tmp = SwingUtilities.computeIntersection(0,0,w,h,tmp);
13.903 +
13.904 + if (tmp.isEmpty()) {
13.905 + // System.out.println("Empty 2");
13.906 + return;
13.907 + }
13.908 +
13.909 + if (dirtyComponents.get(component) != null) {
13.910 + rootDirtyComponent = component;
13.911 + rootDx = dx;
13.912 + rootDy = dy;
13.913 + }
13.914 + }
13.915 +
13.916 + if (dirtyComponent != rootDirtyComponent) {
13.917 + Rectangle r;
13.918 + tmp.setLocation(tmp.x + rootDx - dx,
13.919 + tmp.y + rootDy - dy);
13.920 + r = dirtyComponents.get(rootDirtyComponent);
13.921 + SwingUtilities.computeUnion(tmp.x,tmp.y,tmp.width,tmp.height,r);
13.922 + }
13.923 +
13.924 + // If we haven't seen this root before, then we need to add it to the
13.925 + // list of root dirty Views.
13.926 +
13.927 + if (!roots.contains(rootDirtyComponent))
13.928 + roots.add(rootDirtyComponent);
13.929 + }
13.930 +
13.931 +
13.932 + /**
13.933 + * Returns a string that displays and identifies this
13.934 + * object's properties.
13.935 + *
13.936 + * @return a String representation of this object
13.937 + */
13.938 + public synchronized String toString() {
13.939 + StringBuffer sb = new StringBuffer();
13.940 + if(dirtyComponents != null)
13.941 + sb.append("" + dirtyComponents);
13.942 + return sb.toString();
13.943 + }
13.944 +
13.945 +
13.946 + /**
13.947 + * Return the offscreen buffer that should be used as a double buffer with
13.948 + * the component <code>c</code>.
13.949 + * By default there is a double buffer per RepaintController.
13.950 + * The buffer might be smaller than <code>(proposedWidth,proposedHeight)</code>
13.951 + * This happens when the maximum double buffer size as been set for the receiving
13.952 + * repaint manager.
13.953 + */
13.954 + public Image getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) {
13.955 + RepaintController delegate = getDelegate(c);
13.956 + if (delegate != null) {
13.957 + return delegate.getOffscreenBuffer(c, proposedWidth, proposedHeight);
13.958 + }
13.959 + return _getOffscreenBuffer(c, proposedWidth, proposedHeight);
13.960 + }
13.961 +
13.962 + /**
13.963 + * Return a volatile offscreen buffer that should be used as a
13.964 + * double buffer with the specified component <code>c</code>.
13.965 + * The image returned will be an instance of VolatileImage, or null
13.966 + * if a VolatileImage object could not be instantiated.
13.967 + * This buffer might be smaller than <code>(proposedWidth,proposedHeight)</code>.
13.968 + * This happens when the maximum double buffer size has been set for this
13.969 + * repaint manager.
13.970 + *
13.971 + * @see java.awt.image.VolatileImage
13.972 + * @since 1.4
13.973 + */
13.974 + public Image getVolatileOffscreenBuffer(Component c,
13.975 + int proposedWidth,int proposedHeight) {
13.976 + RepaintController delegate = getDelegate(c);
13.977 + if (delegate != null) {
13.978 + return delegate.getVolatileOffscreenBuffer(c, proposedWidth,
13.979 + proposedHeight);
13.980 + }
13.981 +
13.982 + // If the window is non-opaque, it's double-buffered at peer's level
13.983 + Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
13.984 + if (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
13.985 + Toolkit tk = Toolkit.getDefaultToolkit();
13.986 + if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
13.987 + return null;
13.988 + }
13.989 + }
13.990 +
13.991 + GraphicsConfiguration config = c.getGraphicsConfiguration();
13.992 + if (config == null) {
13.993 + config = GraphicsEnvironment.getLocalGraphicsEnvironment().
13.994 + getDefaultScreenDevice().getDefaultConfiguration();
13.995 + }
13.996 + Dimension maxSize = getDoubleBufferMaximumSize();
13.997 + int width = proposedWidth < 1 ? 1 :
13.998 + (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
13.999 + int height = proposedHeight < 1 ? 1 :
13.1000 + (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
13.1001 + VolatileImage image = volatileMap.get(config);
13.1002 + if (image == null || image.getWidth() < width ||
13.1003 + image.getHeight() < height) {
13.1004 + if (image != null) {
13.1005 + image.flush();
13.1006 + }
13.1007 + image = config.createCompatibleVolatileImage(width, height);
13.1008 + volatileMap.put(config, image);
13.1009 + }
13.1010 + return image;
13.1011 + }
13.1012 +
13.1013 + private Image _getOffscreenBuffer(Component c, int proposedWidth, int proposedHeight) {
13.1014 + Dimension maxSize = getDoubleBufferMaximumSize();
13.1015 + DoubleBufferInfo doubleBuffer;
13.1016 + int width, height;
13.1017 +
13.1018 + // If the window is non-opaque, it's double-buffered at peer's level
13.1019 + Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
13.1020 + if (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
13.1021 + Toolkit tk = Toolkit.getDefaultToolkit();
13.1022 + if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
13.1023 + return null;
13.1024 + }
13.1025 + }
13.1026 +
13.1027 + if (standardDoubleBuffer == null) {
13.1028 + standardDoubleBuffer = new DoubleBufferInfo();
13.1029 + }
13.1030 + doubleBuffer = standardDoubleBuffer;
13.1031 +
13.1032 + width = proposedWidth < 1? 1 :
13.1033 + (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
13.1034 + height = proposedHeight < 1? 1 :
13.1035 + (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
13.1036 +
13.1037 + if (doubleBuffer.needsReset || (doubleBuffer.image != null &&
13.1038 + (doubleBuffer.size.width < width ||
13.1039 + doubleBuffer.size.height < height))) {
13.1040 + doubleBuffer.needsReset = false;
13.1041 + if (doubleBuffer.image != null) {
13.1042 + doubleBuffer.image.flush();
13.1043 + doubleBuffer.image = null;
13.1044 + }
13.1045 + width = Math.max(doubleBuffer.size.width, width);
13.1046 + height = Math.max(doubleBuffer.size.height, height);
13.1047 + }
13.1048 +
13.1049 + Image result = doubleBuffer.image;
13.1050 +
13.1051 + if (doubleBuffer.image == null) {
13.1052 + result = c.createImage(width , height);
13.1053 + doubleBuffer.size = new Dimension(width, height);
13.1054 + if (c instanceof JComponent) {
13.1055 + ((JComponent)c).setCreatedDoubleBuffer(true);
13.1056 + doubleBuffer.image = result;
13.1057 + }
13.1058 + // JComponent will inform us when it is no longer valid
13.1059 + // (via removeNotify) we have no such hook to other components,
13.1060 + // therefore we don't keep a ref to the Component
13.1061 + // (indirectly through the Image) by stashing the image.
13.1062 + }
13.1063 + return result;
13.1064 + }
13.1065 +
13.1066 +
13.1067 + /** Set the maximum double buffer size. **/
13.1068 + public void setDoubleBufferMaximumSize(Dimension d) {
13.1069 + doubleBufferMaxSize = d;
13.1070 + if (doubleBufferMaxSize == null) {
13.1071 + clearImages();
13.1072 + } else {
13.1073 + clearImages(d.width, d.height);
13.1074 + }
13.1075 + }
13.1076 +
13.1077 + private void clearImages() {
13.1078 + clearImages(0, 0);
13.1079 + }
13.1080 +
13.1081 + private void clearImages(int width, int height) {
13.1082 + if (standardDoubleBuffer != null && standardDoubleBuffer.image != null) {
13.1083 + if (standardDoubleBuffer.image.getWidth(null) > width ||
13.1084 + standardDoubleBuffer.image.getHeight(null) > height) {
13.1085 + standardDoubleBuffer.image.flush();
13.1086 + standardDoubleBuffer.image = null;
13.1087 + }
13.1088 + }
13.1089 + // Clear out the VolatileImages
13.1090 + Iterator gcs = volatileMap.keySet().iterator();
13.1091 + while (gcs.hasNext()) {
13.1092 + GraphicsConfiguration gc = (GraphicsConfiguration)gcs.next();
13.1093 + VolatileImage image = volatileMap.get(gc);
13.1094 + if (image.getWidth() > width || image.getHeight() > height) {
13.1095 + image.flush();
13.1096 + gcs.remove();
13.1097 + }
13.1098 + }
13.1099 + }
13.1100 +
13.1101 + /**
13.1102 + * Returns the maximum double buffer size.
13.1103 + *
13.1104 + * @return a Dimension object representing the maximum size
13.1105 + */
13.1106 + public Dimension getDoubleBufferMaximumSize() {
13.1107 + if (doubleBufferMaxSize == null) {
13.1108 + try {
13.1109 + Rectangle virtualBounds = new Rectangle();
13.1110 + GraphicsEnvironment ge = GraphicsEnvironment.
13.1111 + getLocalGraphicsEnvironment();
13.1112 + for (GraphicsDevice gd : ge.getScreenDevices()) {
13.1113 + GraphicsConfiguration gc = gd.getDefaultConfiguration();
13.1114 + virtualBounds = virtualBounds.union(gc.getBounds());
13.1115 + }
13.1116 + doubleBufferMaxSize = new Dimension(virtualBounds.width,
13.1117 + virtualBounds.height);
13.1118 + } catch (HeadlessException e) {
13.1119 + doubleBufferMaxSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
13.1120 + }
13.1121 + }
13.1122 + return doubleBufferMaxSize;
13.1123 + }
13.1124 +
13.1125 + /**
13.1126 + * Enables or disables double buffering in this RepaintController.
13.1127 + * CAUTION: The default value for this property is set for optimal
13.1128 + * paint performance on the given platform and it is not recommended
13.1129 + * that programs modify this property directly.
13.1130 + *
13.1131 + * @param aFlag true to activate double buffering
13.1132 + * @see #isDoubleBufferingEnabled
13.1133 + */
13.1134 + public void setDoubleBufferingEnabled(boolean aFlag) {
13.1135 + doubleBufferingEnabled = aFlag;
13.1136 + PaintManager paintManager = getPaintManager();
13.1137 + if (!aFlag && paintManager.getClass() != PaintManager.class) {
13.1138 + setPaintManager(new PaintManager());
13.1139 + }
13.1140 + }
13.1141 +
13.1142 + /**
13.1143 + * Returns true if this RepaintController is double buffered.
13.1144 + * The default value for this property may vary from platform
13.1145 + * to platform. On platforms where native double buffering
13.1146 + * is supported in the AWT, the default value will be <code>false</code>
13.1147 + * to avoid unnecessary buffering in Swing.
13.1148 + * On platforms where native double buffering is not supported,
13.1149 + * the default value will be <code>true</code>.
13.1150 + *
13.1151 + * @return true if this object is double buffered
13.1152 + */
13.1153 + public boolean isDoubleBufferingEnabled() {
13.1154 + return doubleBufferingEnabled;
13.1155 + }
13.1156 +
13.1157 + /**
13.1158 + * This resets the double buffer. Actually, it marks the double buffer
13.1159 + * as invalid, the double buffer will then be recreated on the next
13.1160 + * invocation of getOffscreenBuffer.
13.1161 + */
13.1162 + void resetDoubleBuffer() {
13.1163 + if (standardDoubleBuffer != null) {
13.1164 + standardDoubleBuffer.needsReset = true;
13.1165 + }
13.1166 + }
13.1167 +
13.1168 + /**
13.1169 + * This resets the volatile double buffer.
13.1170 + */
13.1171 + void resetVolatileDoubleBuffer(GraphicsConfiguration gc) {
13.1172 + Image image = volatileMap.remove(gc);
13.1173 + if (image != null) {
13.1174 + image.flush();
13.1175 + }
13.1176 + }
13.1177 +
13.1178 + /**
13.1179 + * Returns true if we should use the <code>Image</code> returned
13.1180 + * from <code>getVolatileOffscreenBuffer</code> to do double buffering.
13.1181 + */
13.1182 + boolean useVolatileDoubleBuffer() {
13.1183 + return volatileImageBufferEnabled;
13.1184 + }
13.1185 +
13.1186 + /**
13.1187 + * Returns true if the current thread is the thread painting. This
13.1188 + * will return false if no threads are painting.
13.1189 + */
13.1190 + private synchronized boolean isPaintingThread() {
13.1191 + return (Thread.currentThread() == paintThread);
13.1192 + }
13.1193 + //
13.1194 + // Paint methods. You very, VERY rarely need to invoke these.
13.1195 + // They are invoked directly from JComponent's painting code and
13.1196 + // when painting happens outside the normal flow: DefaultDesktopManager
13.1197 + // and JViewport. If you end up needing these methods in other places be
13.1198 + // careful that you don't get stuck in a paint loop.
13.1199 + //
13.1200 +
13.1201 + /**
13.1202 + * Paints a region of a component
13.1203 + *
13.1204 + * @param paintingComponent Component to paint
13.1205 + * @param bufferComponent Component to obtain buffer for
13.1206 + * @param g Graphics to paint to
13.1207 + * @param x X-coordinate
13.1208 + * @param y Y-coordinate
13.1209 + * @param w Width
13.1210 + * @param h Height
13.1211 + */
13.1212 + void paint(JComponent paintingComponent,
13.1213 + JComponent bufferComponent, Graphics g,
13.1214 + int x, int y, int w, int h) {
13.1215 + PaintManager paintManager = getPaintManager();
13.1216 + if (!isPaintingThread()) {
13.1217 + // We're painting to two threads at once. PaintManager deals
13.1218 + // with this a bit better than BufferStrategyPaintManager, use
13.1219 + // it to avoid possible exceptions/corruption.
13.1220 + if (paintManager.getClass() != PaintManager.class) {
13.1221 + paintManager = new PaintManager();
13.1222 + paintManager.RepaintController = this;
13.1223 + }
13.1224 + }
13.1225 + if (!paintManager.paint(paintingComponent, bufferComponent, g,
13.1226 + x, y, w, h)) {
13.1227 + g.setClip(x, y, w, h);
13.1228 + paintingComponent.paintToOffscreen(g, x, y, w, h, x + w, y + h);
13.1229 + }
13.1230 + }
13.1231 +
13.1232 + /**
13.1233 + * Does a copy area on the specified region.
13.1234 + *
13.1235 + * @param clip Whether or not the copyArea needs to be clipped to the
13.1236 + * Component's bounds.
13.1237 + */
13.1238 + void copyArea(JComponent c, Graphics g, int x, int y, int w, int h,
13.1239 + int deltaX, int deltaY, boolean clip) {
13.1240 + getPaintManager().copyArea(c, g, x, y, w, h, deltaX, deltaY, clip);
13.1241 + }
13.1242 +
13.1243 + /**
13.1244 + * Invoked prior to any paint/copyArea method calls. This will
13.1245 + * be followed by an invocation of <code>endPaint</code>.
13.1246 + * <b>WARNING</b>: Callers of this method need to wrap the call
13.1247 + * in a <code>try/finally</code>, otherwise if an exception is thrown
13.1248 + * during the course of painting the RepaintController may
13.1249 + * be left in a state in which the screen is not updated, eg:
13.1250 + * <pre>
13.1251 + * RepaintController.beginPaint();
13.1252 + * try {
13.1253 + * RepaintController.paint(...);
13.1254 + * } finally {
13.1255 + * RepaintController.endPaint();
13.1256 + * }
13.1257 + * </pre>
13.1258 + */
13.1259 + void beginPaint() {
13.1260 + boolean multiThreadedPaint = false;
13.1261 + int paintDepth;
13.1262 + Thread currentThread = Thread.currentThread();
13.1263 + synchronized(this) {
13.1264 + paintDepth = this.paintDepth;
13.1265 + if (paintThread == null || currentThread == paintThread) {
13.1266 + paintThread = currentThread;
13.1267 + this.paintDepth++;
13.1268 + } else {
13.1269 + multiThreadedPaint = true;
13.1270 + }
13.1271 + }
13.1272 + if (!multiThreadedPaint && paintDepth == 0) {
13.1273 + getPaintManager().beginPaint();
13.1274 + }
13.1275 + }
13.1276 +
13.1277 + /**
13.1278 + * Invoked after <code>beginPaint</code> has been invoked.
13.1279 + */
13.1280 + void endPaint() {
13.1281 + if (isPaintingThread()) {
13.1282 + PaintManager paintManager = null;
13.1283 + synchronized(this) {
13.1284 + if (--paintDepth == 0) {
13.1285 + paintManager = getPaintManager();
13.1286 + }
13.1287 + }
13.1288 + if (paintManager != null) {
13.1289 + paintManager.endPaint();
13.1290 + synchronized(this) {
13.1291 + paintThread = null;
13.1292 + }
13.1293 + }
13.1294 + }
13.1295 + }
13.1296 +
13.1297 + /**
13.1298 + * If possible this will show a previously rendered portion of
13.1299 + * a Component. If successful, this will return true, otherwise false.
13.1300 + * <p>
13.1301 + * WARNING: This method is invoked from the native toolkit thread, be
13.1302 + * very careful as to what methods this invokes!
13.1303 + */
13.1304 + boolean show(Container c, int x, int y, int w, int h) {
13.1305 + return getPaintManager().show(c, x, y, w, h);
13.1306 + }
13.1307 +
13.1308 + /**
13.1309 + * Invoked when the doubleBuffered or useTrueDoubleBuffering
13.1310 + * properties of a JRootPane change. This may come in on any thread.
13.1311 + */
13.1312 + void doubleBufferingChanged(JRootPane rootPane) {
13.1313 + getPaintManager().doubleBufferingChanged(rootPane);
13.1314 + }
13.1315 +
13.1316 + /**
13.1317 + * Sets the <code>PaintManager</code> that is used to handle all
13.1318 + * double buffered painting.
13.1319 + *
13.1320 + * @param paintManager The PaintManager to use. Passing in null indicates
13.1321 + * the fallback PaintManager should be used.
13.1322 + */
13.1323 + void setPaintManager(PaintManager paintManager) {
13.1324 + if (paintManager == null) {
13.1325 + paintManager = new PaintManager();
13.1326 + }
13.1327 + PaintManager oldPaintManager;
13.1328 + synchronized(this) {
13.1329 + oldPaintManager = this.paintManager;
13.1330 + this.paintManager = paintManager;
13.1331 + paintManager.RepaintController = this;
13.1332 + }
13.1333 + if (oldPaintManager != null) {
13.1334 + oldPaintManager.dispose();
13.1335 + }
13.1336 + }
13.1337 +
13.1338 + private synchronized PaintManager getPaintManager() {
13.1339 + if (paintManager == null) {
13.1340 + PaintManager paintManager = null;
13.1341 + if (doubleBufferingEnabled && !nativeDoubleBuffering) {
13.1342 + switch (bufferStrategyType) {
13.1343 + case BUFFER_STRATEGY_NOT_SPECIFIED:
13.1344 + Toolkit tk = Toolkit.getDefaultToolkit();
13.1345 + if (tk instanceof SunToolkit) {
13.1346 + SunToolkit stk = (SunToolkit) tk;
13.1347 + if (stk.useBufferPerWindow()) {
13.1348 + paintManager = new BufferStrategyPaintManager();
13.1349 + }
13.1350 + }
13.1351 + break;
13.1352 + case BUFFER_STRATEGY_SPECIFIED_ON:
13.1353 + paintManager = new BufferStrategyPaintManager();
13.1354 + break;
13.1355 + default:
13.1356 + break;
13.1357 + }
13.1358 + }
13.1359 + // null case handled in setPaintManager
13.1360 + setPaintManager(paintManager);
13.1361 + }
13.1362 + return paintManager;
13.1363 + }
13.1364 +
13.1365 + private void scheduleProcessingRunnable() {
13.1366 + scheduleProcessingRunnable(AppContext.getAppContext());
13.1367 + }
13.1368 +
13.1369 + private void scheduleProcessingRunnable(AppContext context) {
13.1370 + if (processingRunnable.markPending()) {
13.1371 + Toolkit tk = Toolkit.getDefaultToolkit();
13.1372 + if (tk instanceof SunToolkit) {
13.1373 + SunToolkit.getSystemEventQueueImplPP(context).
13.1374 + postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
13.1375 + processingRunnable));
13.1376 + } else {
13.1377 + Toolkit.getDefaultToolkit().getSystemEventQueue().
13.1378 + postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
13.1379 + processingRunnable));
13.1380 + }
13.1381 + }
13.1382 + }
13.1383 +
13.1384 +
13.1385 + /**
13.1386 + * PaintManager is used to handle all double buffered painting for
13.1387 + * Swing. Subclasses should call back into the JComponent method
13.1388 + * <code>paintToOffscreen</code> to handle the actual painting.
13.1389 + */
13.1390 + static class PaintManager {
13.1391 + /**
13.1392 + * RepaintController the PaintManager has been installed on.
13.1393 + */
13.1394 + protected RepaintController RepaintController;
13.1395 + boolean isRepaintingRoot;
13.1396 +
13.1397 + /**
13.1398 + * Paints a region of a component
13.1399 + *
13.1400 + * @param paintingComponent Component to paint
13.1401 + * @param bufferComponent Component to obtain buffer for
13.1402 + * @param g Graphics to paint to
13.1403 + * @param x X-coordinate
13.1404 + * @param y Y-coordinate
13.1405 + * @param w Width
13.1406 + * @param h Height
13.1407 + * @return true if painting was successful.
13.1408 + */
13.1409 + public boolean paint(JComponent paintingComponent,
13.1410 + JComponent bufferComponent, Graphics g,
13.1411 + int x, int y, int w, int h) {
13.1412 + // First attempt to use VolatileImage buffer for performance.
13.1413 + // If this fails (which should rarely occur), fallback to a
13.1414 + // standard Image buffer.
13.1415 + boolean paintCompleted = false;
13.1416 + Image offscreen;
13.1417 + if (RepaintController.useVolatileDoubleBuffer() &&
13.1418 + (offscreen = getValidImage(RepaintController.
13.1419 + getVolatileOffscreenBuffer(bufferComponent, w, h))) != null) {
13.1420 + VolatileImage vImage = (java.awt.image.VolatileImage)offscreen;
13.1421 + GraphicsConfiguration gc = bufferComponent.
13.1422 + getGraphicsConfiguration();
13.1423 + for (int i = 0; !paintCompleted &&
13.1424 + i < RepaintController.VOLATILE_LOOP_MAX; i++) {
13.1425 + if (vImage.validate(gc) ==
13.1426 + VolatileImage.IMAGE_INCOMPATIBLE) {
13.1427 + RepaintController.resetVolatileDoubleBuffer(gc);
13.1428 + offscreen = RepaintController.getVolatileOffscreenBuffer(
13.1429 + bufferComponent,w, h);
13.1430 + vImage = (java.awt.image.VolatileImage)offscreen;
13.1431 + }
13.1432 + paintDoubleBuffered(paintingComponent, vImage, g, x, y,
13.1433 + w, h);
13.1434 + paintCompleted = !vImage.contentsLost();
13.1435 + }
13.1436 + }
13.1437 + // VolatileImage painting loop failed, fallback to regular
13.1438 + // offscreen buffer
13.1439 + if (!paintCompleted && (offscreen = getValidImage(
13.1440 + RepaintController.getOffscreenBuffer(
13.1441 + bufferComponent, w, h))) != null) {
13.1442 + paintDoubleBuffered(paintingComponent, offscreen, g, x, y, w,
13.1443 + h);
13.1444 + paintCompleted = true;
13.1445 + }
13.1446 + return paintCompleted;
13.1447 + }
13.1448 +
13.1449 + /**
13.1450 + * Does a copy area on the specified region.
13.1451 + */
13.1452 + public void copyArea(JComponent c, Graphics g, int x, int y, int w,
13.1453 + int h, int deltaX, int deltaY, boolean clip) {
13.1454 + g.copyArea(x, y, w, h, deltaX, deltaY);
13.1455 + }
13.1456 +
13.1457 + /**
13.1458 + * Invoked prior to any calls to paint or copyArea.
13.1459 + */
13.1460 + public void beginPaint() {
13.1461 + }
13.1462 +
13.1463 + /**
13.1464 + * Invoked to indicate painting has been completed.
13.1465 + */
13.1466 + public void endPaint() {
13.1467 + }
13.1468 +
13.1469 + /**
13.1470 + * Shows a region of a previously rendered component. This
13.1471 + * will return true if successful, false otherwise. The default
13.1472 + * implementation returns false.
13.1473 + */
13.1474 + public boolean show(Container c, int x, int y, int w, int h) {
13.1475 + return false;
13.1476 + }
13.1477 +
13.1478 + /**
13.1479 + * Invoked when the doubleBuffered or useTrueDoubleBuffering
13.1480 + * properties of a JRootPane change. This may come in on any thread.
13.1481 + */
13.1482 + public void doubleBufferingChanged(JRootPane rootPane) {
13.1483 + }
13.1484 +
13.1485 + /**
13.1486 + * Paints a portion of a component to an offscreen buffer.
13.1487 + */
13.1488 + protected void paintDoubleBuffered(JComponent c, Image image,
13.1489 + Graphics g, int clipX, int clipY,
13.1490 + int clipW, int clipH) {
13.1491 + Graphics osg = image.getGraphics();
13.1492 + int bw = Math.min(clipW, image.getWidth(null));
13.1493 + int bh = Math.min(clipH, image.getHeight(null));
13.1494 + int x,y,maxx,maxy;
13.1495 +
13.1496 + try {
13.1497 + for(x = clipX, maxx = clipX+clipW; x < maxx ; x += bw ) {
13.1498 + for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) {
13.1499 + osg.translate(-x, -y);
13.1500 + osg.setClip(x,y,bw,bh);
13.1501 + c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy);
13.1502 + g.setClip(x, y, bw, bh);
13.1503 + g.drawImage(image, x, y, c);
13.1504 + osg.translate(x, y);
13.1505 + }
13.1506 + }
13.1507 + } finally {
13.1508 + osg.dispose();
13.1509 + }
13.1510 + }
13.1511 +
13.1512 + /**
13.1513 + * If <code>image</code> is non-null with a positive size it
13.1514 + * is returned, otherwise null is returned.
13.1515 + */
13.1516 + private Image getValidImage(Image image) {
13.1517 + if (image != null && image.getWidth(null) > 0 &&
13.1518 + image.getHeight(null) > 0) {
13.1519 + return image;
13.1520 + }
13.1521 + return null;
13.1522 + }
13.1523 +
13.1524 + /**
13.1525 + * Schedules a repaint for the specified component. This differs
13.1526 + * from <code>root.repaint</code> in that if the RepaintController is
13.1527 + * currently processing paint requests it'll process this request
13.1528 + * with the current set of requests.
13.1529 + */
13.1530 + protected void repaintRoot(JComponent root) {
13.1531 + assert (RepaintController.repaintRoot == null);
13.1532 + if (RepaintController.painting) {
13.1533 + RepaintController.repaintRoot = root;
13.1534 + }
13.1535 + else {
13.1536 + root.repaint();
13.1537 + }
13.1538 + }
13.1539 +
13.1540 + /**
13.1541 + * Returns true if the component being painted is the root component
13.1542 + * that was previously passed to <code>repaintRoot</code>.
13.1543 + */
13.1544 + protected boolean isRepaintingRoot() {
13.1545 + return isRepaintingRoot;
13.1546 + }
13.1547 +
13.1548 + /**
13.1549 + * Cleans up any state. After invoked the PaintManager will no
13.1550 + * longer be used anymore.
13.1551 + */
13.1552 + protected void dispose() {
13.1553 + }
13.1554 + }
13.1555 +
13.1556 +
13.1557 + private class DoubleBufferInfo {
13.1558 + public Image image;
13.1559 + public Dimension size;
13.1560 + public boolean needsReset = false;
13.1561 + }
13.1562 +
13.1563 +
13.1564 + /**
13.1565 + * Listener installed to detect display changes. When display changes,
13.1566 + * schedules a callback to notify all RepaintControllers of the display
13.1567 + * changes. Only one DisplayChangedHandler is ever installed. The
13.1568 + * singleton instance will schedule notification for all AppContexts.
13.1569 + */
13.1570 + private static final class DisplayChangedHandler implements
13.1571 + DisplayChangedListener {
13.1572 + public void displayChanged() {
13.1573 + scheduleDisplayChanges();
13.1574 + }
13.1575 +
13.1576 + public void paletteChanged() {
13.1577 + }
13.1578 +
13.1579 + private void scheduleDisplayChanges() {
13.1580 + // To avoid threading problems, we notify each RepaintController
13.1581 + // on the thread it was created on.
13.1582 + for (Object c : AppContext.getAppContexts()) {
13.1583 + AppContext context = (AppContext) c;
13.1584 + synchronized(context) {
13.1585 + if (!context.isDisposed()) {
13.1586 + EventQueue eventQueue = (EventQueue)context.get(
13.1587 + AppContext.EVENT_QUEUE_KEY);
13.1588 + if (eventQueue != null) {
13.1589 + eventQueue.postEvent(new InvocationEvent(
13.1590 + Toolkit.getDefaultToolkit(),
13.1591 + new DisplayChangedRunnable()));
13.1592 + }
13.1593 + }
13.1594 + }
13.1595 + }
13.1596 + }
13.1597 + }
13.1598 +
13.1599 +
13.1600 + private static final class DisplayChangedRunnable implements Runnable {
13.1601 + public void run() {
13.1602 + RepaintController.currentManager((JComponent)null).displayChanged();
13.1603 + }
13.1604 + }
13.1605 +
13.1606 +
13.1607 + /**
13.1608 + * Runnable used to process all repaint/revalidate requests.
13.1609 + */
13.1610 + private final class ProcessingRunnable implements Runnable {
13.1611 + // If true, we're wainting on the EventQueue.
13.1612 + private boolean pending;
13.1613 +
13.1614 + /**
13.1615 + * Marks this processing runnable as pending. If this was not
13.1616 + * already marked as pending, true is returned.
13.1617 + */
13.1618 + public synchronized boolean markPending() {
13.1619 + if (!pending) {
13.1620 + pending = true;
13.1621 + return true;
13.1622 + }
13.1623 + return false;
13.1624 + }
13.1625 +
13.1626 + public void run() {
13.1627 + synchronized (this) {
13.1628 + pending = false;
13.1629 + }
13.1630 + // First pass, flush any heavy paint events into real paint
13.1631 + // events. If there are pending heavy weight requests this will
13.1632 + // result in q'ing this request up one more time. As
13.1633 + // long as no other requests come in between now and the time
13.1634 + // the second one is processed nothing will happen. This is not
13.1635 + // ideal, but the logic needed to suppress the second request is
13.1636 + // more headache than it's worth.
13.1637 + scheduleHeavyWeightPaints();
13.1638 + // Do the actual validation and painting.
13.1639 + validateInvalidComponents();
13.1640 + prePaintDirtyRegions();
13.1641 + }
13.1642 + }
13.1643 + private RepaintController getDelegate(Component c) {
13.1644 + RepaintController delegate = SwingUtilities3.getDelegateRepaintController(c);
13.1645 + if (this == delegate) {
13.1646 + delegate = null;
13.1647 + }
13.1648 + return delegate;
13.1649 + }
13.1650 +}
14.1 --- a/src/share/classes/javax/swing/RepaintManager.java Fri Jun 19 21:46:14 2009 +0200
14.2 +++ b/src/share/classes/javax/swing/RepaintManager.java Sat Jun 20 22:10:34 2009 +0200
14.3 @@ -27,13 +27,13 @@
14.4
14.5 import java.awt.*;
14.6 import java.awt.event.*;
14.7 -import java.awt.peer.ComponentPeer;
14.8 -import java.awt.peer.ContainerPeer;
14.9 import java.awt.image.VolatileImage;
14.10 import java.security.AccessController;
14.11 import java.util.*;
14.12 import java.applet.*;
14.13
14.14 +import javax.swing.RepaintController.PaintManager;
14.15 +
14.16 import sun.awt.AWTAccessor;
14.17 import sun.awt.AppContext;
14.18 import sun.awt.DisplayChangedListener;
14.19 @@ -56,155 +56,24 @@
14.20 * appropriate <code>addDirtyRegion</code> method.
14.21 *
14.22 * @author Arnaud Weber
14.23 + * @deprecated Use RepaintController
14.24 */
14.25 +@Deprecated
14.26 public class RepaintManager
14.27 {
14.28 - /**
14.29 - * Whether or not the RepaintManager should handle paint requests
14.30 - * for top levels.
14.31 - */
14.32 - static final boolean HANDLE_TOP_LEVEL_PAINT;
14.33 -
14.34 - private static final short BUFFER_STRATEGY_NOT_SPECIFIED = 0;
14.35 - private static final short BUFFER_STRATEGY_SPECIFIED_ON = 1;
14.36 - private static final short BUFFER_STRATEGY_SPECIFIED_OFF = 2;
14.37 -
14.38 - private static final short BUFFER_STRATEGY_TYPE;
14.39 -
14.40 - /**
14.41 - * Maps from GraphicsConfiguration to VolatileImage.
14.42 - */
14.43 - private Map<GraphicsConfiguration,VolatileImage> volatileMap = new
14.44 - HashMap<GraphicsConfiguration,VolatileImage>(1);
14.45 -
14.46 + // JST-XXX:
14.47 + // Deprecation note: One possibility is to subclass RepaintController,
14.48 + // other delegate. This code delegates, but it is yet to be seen what
14.49 + // is simpler and more compatible.
14.50 //
14.51 - // As of 1.6 Swing handles scheduling of paint events from native code.
14.52 - // That is, SwingPaintEventDispatcher is invoked on the toolkit thread,
14.53 - // which in turn invokes nativeAddDirtyRegion. Because this is invoked
14.54 - // from the native thread we can not invoke any public methods and so
14.55 - // we introduce these added maps. So, any time nativeAddDirtyRegion is
14.56 - // invoked the region is added to hwDirtyComponents and a work request
14.57 - // is scheduled. When the work request is processed all entries in
14.58 - // this map are pushed to the real map (dirtyComponents) and then
14.59 - // painted with the rest of the components.
14.60 - //
14.61 - private Map<Container,Rectangle> hwDirtyComponents;
14.62 -
14.63 - private Map<Component,Rectangle> dirtyComponents;
14.64 - private Map<Component,Rectangle> tmpDirtyComponents;
14.65 - private java.util.List<Component> invalidComponents;
14.66 -
14.67 - // List of Runnables that need to be processed before painting from AWT.
14.68 - private java.util.List<Runnable> runnableList;
14.69 -
14.70 - boolean doubleBufferingEnabled = true;
14.71 -
14.72 - private Dimension doubleBufferMaxSize;
14.73 -
14.74 - // Support for both the standard and volatile offscreen buffers exists to
14.75 - // provide backwards compatibility for the [rare] programs which may be
14.76 - // calling getOffScreenBuffer() and not expecting to get a VolatileImage.
14.77 - // Swing internally is migrating to use *only* the volatile image buffer.
14.78 -
14.79 - // Support for standard offscreen buffer
14.80 - //
14.81 - DoubleBufferInfo standardDoubleBuffer;
14.82 -
14.83 - /**
14.84 - * Object responsible for hanlding core paint functionality.
14.85 - */
14.86 - private PaintManager paintManager;
14.87
14.88 private static final Object repaintManagerKey = RepaintManager.class;
14.89 -
14.90 - // Whether or not a VolatileImage should be used for double-buffered painting
14.91 - static boolean volatileImageBufferEnabled = true;
14.92 - /**
14.93 - * Value of the system property awt.nativeDoubleBuffering.
14.94 - */
14.95 - private static boolean nativeDoubleBuffering;
14.96 -
14.97 - // The maximum number of times Swing will attempt to use the VolatileImage
14.98 - // buffer during a paint operation.
14.99 - private static final int VOLATILE_LOOP_MAX = 2;
14.100 -
14.101 - /**
14.102 - * Number of <code>beginPaint</code> that have been invoked.
14.103 - */
14.104 - private int paintDepth = 0;
14.105 -
14.106 - /**
14.107 - * Type of buffer strategy to use. Will be one of the BUFFER_STRATEGY_
14.108 - * constants.
14.109 - */
14.110 - private short bufferStrategyType;
14.111 -
14.112 - //
14.113 - // BufferStrategyPaintManager has the unique characteristic that it
14.114 - // must deal with the buffer being lost while painting to it. For
14.115 - // example, if we paint a component and show it and the buffer has
14.116 - // become lost we must repaint the whole window. To deal with that
14.117 - // the PaintManager calls into repaintRoot, and if we're still in
14.118 - // the process of painting the repaintRoot field is set to the JRootPane
14.119 - // and after the current JComponent.paintImmediately call finishes
14.120 - // paintImmediately will be invoked on the repaintRoot. In this
14.121 - // way we don't try to show garbage to the screen.
14.122 - //
14.123 - /**
14.124 - * True if we're in the process of painting the dirty regions. This is
14.125 - * set to true in <code>paintDirtyRegions</code>.
14.126 - */
14.127 - private boolean painting;
14.128 - /**
14.129 - * If the PaintManager calls into repaintRoot during painting this field
14.130 - * will be set to the root.
14.131 - */
14.132 - private JComponent repaintRoot;
14.133 -
14.134 - /**
14.135 - * The Thread that has initiated painting. If null it
14.136 - * indicates painting is not currently in progress.
14.137 - */
14.138 - private Thread paintThread;
14.139 -
14.140 - /**
14.141 - * Runnable used to process all repaint/revalidate requests.
14.142 - */
14.143 - private final ProcessingRunnable processingRunnable;
14.144 -
14.145 -
14.146 - static {
14.147 - volatileImageBufferEnabled = "true".equals(AccessController.
14.148 - doPrivileged(new GetPropertyAction(
14.149 - "swing.volatileImageBufferEnabled", "true")));
14.150 - boolean headless = GraphicsEnvironment.isHeadless();
14.151 - if (volatileImageBufferEnabled && headless) {
14.152 - volatileImageBufferEnabled = false;
14.153 - }
14.154 - nativeDoubleBuffering = "true".equals(AccessController.doPrivileged(
14.155 - new GetPropertyAction("awt.nativeDoubleBuffering")));
14.156 - String bs = AccessController.doPrivileged(
14.157 - new GetPropertyAction("swing.bufferPerWindow"));
14.158 - if (headless) {
14.159 - BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
14.160 - }
14.161 - else if (bs == null) {
14.162 - BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_NOT_SPECIFIED;
14.163 - }
14.164 - else if ("true".equals(bs)) {
14.165 - BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_ON;
14.166 - }
14.167 - else {
14.168 - BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
14.169 - }
14.170 - HANDLE_TOP_LEVEL_PAINT = "true".equals(AccessController.doPrivileged(
14.171 - new GetPropertyAction("swing.handleTopLevelPaint", "true")));
14.172 - GraphicsEnvironment ge = GraphicsEnvironment.
14.173 - getLocalGraphicsEnvironment();
14.174 - if (ge instanceof SunGraphicsEnvironment) {
14.175 - ((SunGraphicsEnvironment)ge).addDisplayChangedListener(
14.176 - new DisplayChangedHandler());
14.177 - }
14.178 + private final RepaintController delegate;
14.179 + public RepaintManager() {
14.180 + this(new RepaintController());
14.181 + }
14.182 + private RepaintManager(RepaintController rc) {
14.183 + this.delegate = rc;
14.184 }
14.185
14.186 /**
14.187 @@ -229,12 +98,7 @@
14.188 * AppContext this will return null.
14.189 */
14.190 static RepaintManager currentManager(AppContext appContext) {
14.191 - RepaintManager rm = (RepaintManager)appContext.get(repaintManagerKey);
14.192 - if (rm == null) {
14.193 - rm = new RepaintManager(BUFFER_STRATEGY_TYPE);
14.194 - appContext.put(repaintManagerKey, rm);
14.195 - }
14.196 - return rm;
14.197 + return new RepaintManager(RepaintController.currentManager(appContext));
14.198 }
14.199
14.200 /**
14.201 @@ -259,6 +123,7 @@
14.202 * @param aRepaintManager the RepaintManager object to use
14.203 */
14.204 public static void setCurrentManager(RepaintManager aRepaintManager) {
14.205 + // JST-XXX: Not fully correct.
14.206 if (aRepaintManager != null) {
14.207 SwingUtilities.appContextPut(repaintManagerKey, aRepaintManager);
14.208 } else {
14.209 @@ -267,36 +132,6 @@
14.210 }
14.211
14.212 /**
14.213 - * Create a new RepaintManager instance. You rarely call this constructor.
14.214 - * directly. To get the default RepaintManager, use
14.215 - * RepaintManager.currentManager(JComponent) (normally "this").
14.216 - */
14.217 - public RepaintManager() {
14.218 - // Because we can't know what a subclass is doing with the
14.219 - // volatile image we immediately punt in subclasses. If this
14.220 - // poses a problem we'll need a more sophisticated detection algorithm,
14.221 - // or API.
14.222 - this(BUFFER_STRATEGY_SPECIFIED_OFF);
14.223 - }
14.224 -
14.225 - private RepaintManager(short bufferStrategyType) {
14.226 - // If native doublebuffering is being used, do NOT use
14.227 - // Swing doublebuffering.
14.228 - doubleBufferingEnabled = !nativeDoubleBuffering;
14.229 - synchronized(this) {
14.230 - dirtyComponents = new IdentityHashMap<Component,Rectangle>();
14.231 - tmpDirtyComponents = new IdentityHashMap<Component,Rectangle>();
14.232 - this.bufferStrategyType = bufferStrategyType;
14.233 - hwDirtyComponents = new IdentityHashMap<Container,Rectangle>();
14.234 - }
14.235 - processingRunnable = new ProcessingRunnable();
14.236 - }
14.237 -
14.238 - private void displayChanged() {
14.239 - clearImages();
14.240 - }
14.241 -
14.242 - /**
14.243 * Mark the component as in need of layout and queue a runnable
14.244 * for the event dispatching thread that will validate the components
14.245 * first isValidateRoot() ancestor.
14.246 @@ -304,163 +139,18 @@
14.247 * @see JComponent#isValidateRoot
14.248 * @see #removeInvalidComponent
14.249 */
14.250 - public synchronized void addInvalidComponent(JComponent invalidComponent)
14.251 + public void addInvalidComponent(JComponent invalidComponent)
14.252 {
14.253 - RepaintManager delegate = getDelegate(invalidComponent);
14.254 - if (delegate != null) {
14.255 - delegate.addInvalidComponent(invalidComponent);
14.256 - return;
14.257 - }
14.258 - Component validateRoot = null;
14.259 -
14.260 - /* Find the first JComponent ancestor of this component whose
14.261 - * isValidateRoot() method returns true.
14.262 - */
14.263 - for(Component c = invalidComponent; c != null; c = c.getParent()) {
14.264 - if ((c instanceof CellRendererPane) || (c.getPeer() == null)) {
14.265 - return;
14.266 - }
14.267 - if ((c instanceof JComponent) && (((JComponent)c).isValidateRoot())) {
14.268 - validateRoot = c;
14.269 - break;
14.270 - }
14.271 - }
14.272 -
14.273 - /* There's no validateRoot to apply validate to, so we're done.
14.274 - */
14.275 - if (validateRoot == null) {
14.276 - return;
14.277 - }
14.278 -
14.279 - /* If the validateRoot and all of its ancestors aren't visible
14.280 - * then we don't do anything. While we're walking up the tree
14.281 - * we find the root Window or Applet.
14.282 - */
14.283 - Component root = null;
14.284 -
14.285 - for(Component c = validateRoot; c != null; c = c.getParent()) {
14.286 - if (!c.isVisible() || (c.getPeer() == null)) {
14.287 - return;
14.288 - }
14.289 - if ((c instanceof Window) || SwingUtilities2.isApplet(c)) {
14.290 - root = c;
14.291 - break;
14.292 - }
14.293 - }
14.294 -
14.295 - if (root == null) {
14.296 - return;
14.297 - }
14.298 -
14.299 - /* Lazily create the invalidateComponents vector and add the
14.300 - * validateRoot if it's not there already. If this validateRoot
14.301 - * is already in the vector, we're done.
14.302 - */
14.303 - if (invalidComponents == null) {
14.304 - invalidComponents = new ArrayList<Component>();
14.305 - }
14.306 - else {
14.307 - int n = invalidComponents.size();
14.308 - for(int i = 0; i < n; i++) {
14.309 - if(validateRoot == invalidComponents.get(i)) {
14.310 - return;
14.311 - }
14.312 - }
14.313 - }
14.314 - invalidComponents.add(validateRoot);
14.315 -
14.316 - // Queue a Runnable to invoke paintDirtyRegions and
14.317 - // validateInvalidComponents.
14.318 - scheduleProcessingRunnable();
14.319 + delegate.addInvalidComponent(invalidComponent);
14.320 }
14.321
14.322 -
14.323 /**
14.324 * Remove a component from the list of invalid components.
14.325 *
14.326 * @see #addInvalidComponent
14.327 */
14.328 - public synchronized void removeInvalidComponent(JComponent component) {
14.329 - RepaintManager delegate = getDelegate(component);
14.330 - if (delegate != null) {
14.331 - delegate.removeInvalidComponent(component);
14.332 - return;
14.333 - }
14.334 - if(invalidComponents != null) {
14.335 - int index = invalidComponents.indexOf(component);
14.336 - if(index != -1) {
14.337 - invalidComponents.remove(index);
14.338 - }
14.339 - }
14.340 - }
14.341 -
14.342 -
14.343 - /**
14.344 - * Add a component in the list of components that should be refreshed.
14.345 - * If <i>c</i> already has a dirty region, the rectangle <i>(x,y,w,h)</i>
14.346 - * will be unioned with the region that should be redrawn.
14.347 - *
14.348 - * @see JComponent#repaint
14.349 - */
14.350 - private void addDirtyRegion0(Container c, int x, int y, int w, int h) {
14.351 - /* Special cases we don't have to bother with.
14.352 - */
14.353 - if ((w <= 0) || (h <= 0) || (c == null)) {
14.354 - return;
14.355 - }
14.356 -
14.357 - if ((c.getWidth() <= 0) || (c.getHeight() <= 0)) {
14.358 - return;
14.359 - }
14.360 -
14.361 - if (extendDirtyRegion(c, x, y, w, h)) {
14.362 - // Component was already marked as dirty, region has been
14.363 - // extended, no need to continue.
14.364 - return;
14.365 - }
14.366 -
14.367 - /* Make sure that c and all it ancestors (up to an Applet or
14.368 - * Window) are visible. This loop has the same effect as
14.369 - * checking c.isShowing() (and note that it's still possible
14.370 - * that c is completely obscured by an opaque ancestor in
14.371 - * the specified rectangle).
14.372 - */
14.373 - Component root = null;
14.374 -
14.375 - // Note: We can't synchronize around this, Frame.getExtendedState
14.376 - // is synchronized so that if we were to synchronize around this
14.377 - // it could lead to the possibility of getting locks out
14.378 - // of order and deadlocking.
14.379 - for (Container p = c; p != null; p = p.getParent()) {
14.380 - if (!p.isVisible() || (p.getPeer() == null)) {
14.381 - return;
14.382 - }
14.383 - if ((p instanceof Window) || SwingUtilities2.isApplet(p)) {
14.384 - // Iconified frames are still visible!
14.385 - if (p instanceof Frame &&
14.386 - (((Frame)p).getExtendedState() & Frame.ICONIFIED) ==
14.387 - Frame.ICONIFIED) {
14.388 - return;
14.389 - }
14.390 - root = p;
14.391 - break;
14.392 - }
14.393 - }
14.394 -
14.395 - if (root == null) return;
14.396 -
14.397 - synchronized(this) {
14.398 - if (extendDirtyRegion(c, x, y, w, h)) {
14.399 - // In between last check and this check another thread
14.400 - // queued up runnable, can bail here.
14.401 - return;
14.402 - }
14.403 - dirtyComponents.put(c, new Rectangle(x, y, w, h));
14.404 - }
14.405 -
14.406 - // Queue a Runnable to invoke paintDirtyRegions and
14.407 - // validateInvalidComponents.
14.408 - scheduleProcessingRunnable();
14.409 + public void removeInvalidComponent(JComponent component) {
14.410 + delegate.removeInvalidComponent(component);
14.411 }
14.412
14.413 /**
14.414 @@ -477,12 +167,7 @@
14.415 */
14.416 public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
14.417 {
14.418 - RepaintManager delegate = getDelegate(c);
14.419 - if (delegate != null) {
14.420 - delegate.addDirtyRegion(c, x, y, w, h);
14.421 - return;
14.422 - }
14.423 - addDirtyRegion0(c, x, y, w, h);
14.424 + delegate.addDirtyRegion(c, x, y, w, h);
14.425 }
14.426
14.427 /**
14.428 @@ -500,7 +185,7 @@
14.429 * @since 1.6
14.430 */
14.431 public void addDirtyRegion(Window window, int x, int y, int w, int h) {
14.432 - addDirtyRegion0(window, x, y, w, h);
14.433 + delegate.addDirtyRegion(window, x, y, w, h);
14.434 }
14.435
14.436 /**
14.437 @@ -516,89 +201,7 @@
14.438 * @since 1.6
14.439 */
14.440 public void addDirtyRegion(Applet applet, int x, int y, int w, int h) {
14.441 - addDirtyRegion0(applet, x, y, w, h);
14.442 - }
14.443 -
14.444 - void scheduleHeavyWeightPaints() {
14.445 - Map<Container,Rectangle> hws;
14.446 -
14.447 - synchronized(this) {
14.448 - if (hwDirtyComponents.size() == 0) {
14.449 - return;
14.450 - }
14.451 - hws = hwDirtyComponents;
14.452 - hwDirtyComponents = new IdentityHashMap<Container,Rectangle>();
14.453 - }
14.454 - for (Container hw : hws.keySet()) {
14.455 - Rectangle dirty = hws.get(hw);
14.456 - if (hw instanceof Window) {
14.457 - addDirtyRegion((Window)hw, dirty.x, dirty.y,
14.458 - dirty.width, dirty.height);
14.459 - }
14.460 - else if (SwingUtilities2.isApplet(hw)) {
14.461 - addDirtyRegion((Applet)hw, dirty.x, dirty.y,
14.462 - dirty.width, dirty.height);
14.463 - }
14.464 - else { // SwingHeavyWeight
14.465 - addDirtyRegion0(hw, dirty.x, dirty.y,
14.466 - dirty.width, dirty.height);
14.467 - }
14.468 - }
14.469 - }
14.470 -
14.471 - //
14.472 - // This is called from the toolkit thread when a native expose is
14.473 - // received.
14.474 - //
14.475 - void nativeAddDirtyRegion(AppContext appContext, Container c,
14.476 - int x, int y, int w, int h) {
14.477 - if (w > 0 && h > 0) {
14.478 - synchronized(this) {
14.479 - Rectangle dirty = hwDirtyComponents.get(c);
14.480 - if (dirty == null) {
14.481 - hwDirtyComponents.put(c, new Rectangle(x, y, w, h));
14.482 - }
14.483 - else {
14.484 - hwDirtyComponents.put(c, SwingUtilities.computeUnion(
14.485 - x, y, w, h, dirty));
14.486 - }
14.487 - }
14.488 - scheduleProcessingRunnable(appContext);
14.489 - }
14.490 - }
14.491 -
14.492 - //
14.493 - // This is called from the toolkit thread when awt needs to run a
14.494 - // Runnable before we paint.
14.495 - //
14.496 - void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c,
14.497 - Runnable r) {
14.498 - synchronized(this) {
14.499 - if (runnableList == null) {
14.500 - runnableList = new LinkedList<Runnable>();
14.501 - }
14.502 - runnableList.add(r);
14.503 - }
14.504 - scheduleProcessingRunnable(appContext);
14.505 - }
14.506 -
14.507 - /**
14.508 - * Extends the dirty region for the specified component to include
14.509 - * the new region.
14.510 - *
14.511 - * @return false if <code>c</code> is not yet marked dirty.
14.512 - */
14.513 - private synchronized boolean extendDirtyRegion(
14.514 - Component c, int x, int y, int w, int h) {
14.515 - Rectangle r = dirtyComponents.get(c);
14.516 - if (r != null) {
14.517 - // A non-null r implies c is already marked as dirty,
14.518 - // and that the parent is valid. Therefore we can
14.519 - // just union the rect and bail.
14.520 - SwingUtilities.computeUnion(x, y, w, h, r);
14.521 - return true;
14.522 - }
14.523 - return false;
14.524 + delegate.addDirtyRegion0(applet, x, y, w, h);
14.525 }
14.526
14.527 /** Return the current dirty region for a component.
14.528 @@ -606,18 +209,7 @@
14.529 * dirty.
14.530 */
14.531 public Rectangle getDirtyRegion(JComponent aComponent) {
14.532 - RepaintManager delegate = getDelegate(aComponent);
14.533 - if (delegate != null) {
14.534 - return delegate.getDirtyRegion(aComponent);
14.535 - }
14.536 - Rectangle r;
14.537 - synchronized(this) {
14.538 - r = dirtyComponents.get(aComponent);
14.539 - }
14.540 - if(r == null)
14.541 - return new Rectangle(0,0,0,0);
14.542 - else
14.543 - return new Rectangle(r);
14.544 + return delegate.getDirtyRegion(aComponent);
14.545 }
14.546
14.547 /**
14.548 @@ -625,12 +217,7 @@
14.549 * completely painted during the next paintDirtyRegions() call.
14.550 */
14.551 public void markCompletelyDirty(JComponent aComponent) {
14.552 - RepaintManager delegate = getDelegate(aComponent);
14.553 - if (delegate != null) {
14.554 - delegate.markCompletelyDirty(aComponent);
14.555 - return;
14.556 - }
14.557 - addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE);
14.558 + delegate.markCompletelyDirty(aComponent);
14.559 }
14.560
14.561 /**
14.562 @@ -638,14 +225,7 @@
14.563 * get painted during the next paintDirtyRegions() call.
14.564 */
14.565 public void markCompletelyClean(JComponent aComponent) {
14.566 - RepaintManager delegate = getDelegate(aComponent);
14.567 - if (delegate != null) {
14.568 - delegate.markCompletelyClean(aComponent);
14.569 - return;
14.570 - }
14.571 - synchronized(this) {
14.572 - dirtyComponents.remove(aComponent);
14.573 - }
14.574 + delegate.markCompletelyClean(aComponent);
14.575 }
14.576
14.577 /**
14.578 @@ -655,18 +235,7 @@
14.579 * if it return true.
14.580 */
14.581 public boolean isCompletelyDirty(JComponent aComponent) {
14.582 - RepaintManager delegate = getDelegate(aComponent);
14.583 - if (delegate != null) {
14.584 - return delegate.isCompletelyDirty(aComponent);
14.585 - }
14.586 - Rectangle r;
14.587 -
14.588 - r = getDirtyRegion(aComponent);
14.589 - if(r.width == Integer.MAX_VALUE &&
14.590 - r.height == Integer.MAX_VALUE)
14.591 - return true;
14.592 - else
14.593 - return false;
14.594 + return delegate.isCompletelyDirty(aComponent);
14.595 }
14.596
14.597
14.598 @@ -675,77 +244,7 @@
14.599 * @see #addInvalidComponent
14.600 */
14.601 public void validateInvalidComponents() {
14.602 - java.util.List<Component> ic;
14.603 - synchronized(this) {
14.604 - if(invalidComponents == null) {
14.605 - return;
14.606 - }
14.607 - ic = invalidComponents;
14.608 - invalidComponents = null;
14.609 - }
14.610 - int n = ic.size();
14.611 - for(int i = 0; i < n; i++) {
14.612 - ic.get(i).validate();
14.613 - }
14.614 - }
14.615 -
14.616 -
14.617 - /**
14.618 - * This is invoked to process paint requests. It's needed
14.619 - * for backward compatability in so far as RepaintManager would previously
14.620 - * not see paint requests for top levels, so, we have to make sure
14.621 - * a subclass correctly paints any dirty top levels.
14.622 - */
14.623 - private void prePaintDirtyRegions() {
14.624 - Map<Component,Rectangle> dirtyComponents;
14.625 - java.util.List<Runnable> runnableList;
14.626 - synchronized(this) {
14.627 - dirtyComponents = this.dirtyComponents;
14.628 - runnableList = this.runnableList;
14.629 - this.runnableList = null;
14.630 - }
14.631 - if (runnableList != null) {
14.632 - for (Runnable runnable : runnableList) {
14.633 - runnable.run();
14.634 - }
14.635 - }
14.636 - paintDirtyRegions();
14.637 - if (dirtyComponents.size() > 0) {
14.638 - // This'll only happen if a subclass isn't correctly dealing
14.639 - // with toplevels.
14.640 - paintDirtyRegions(dirtyComponents);
14.641 - }
14.642 - }
14.643 -
14.644 - private void updateWindows(Map<Component,Rectangle> dirtyComponents) {
14.645 - Toolkit toolkit = Toolkit.getDefaultToolkit();
14.646 - if (!(toolkit instanceof SunToolkit &&
14.647 - ((SunToolkit)toolkit).needUpdateWindow()))
14.648 - {
14.649 - return;
14.650 - }
14.651 -
14.652 - Set<Window> windows = new HashSet<Window>();
14.653 - Set<Component> dirtyComps = dirtyComponents.keySet();
14.654 - for (Iterator<Component> it = dirtyComps.iterator(); it.hasNext();) {
14.655 - Component dirty = it.next();
14.656 - Window window = dirty instanceof Window ?
14.657 - (Window)dirty :
14.658 - SwingUtilities.getWindowAncestor(dirty);
14.659 - if (window != null &&
14.660 - !AWTAccessor.getWindowAccessor().isOpaque(window))
14.661 - {
14.662 - windows.add(window);
14.663 - }
14.664 - }
14.665 -
14.666 - for (Window window : windows) {
14.667 - AWTAccessor.getWindowAccessor().updateWindow(window);
14.668 - }
14.669 - }
14.670 -
14.671 - boolean isPainting() {
14.672 - return painting;
14.673 + delegate.validateInvalidComponents();
14.674 }
14.675
14.676 /**
14.677 @@ -754,208 +253,17 @@
14.678 * @see #addDirtyRegion
14.679 */
14.680 public void paintDirtyRegions() {
14.681 - synchronized(this) { // swap for thread safety
14.682 - Map<Component,Rectangle> tmp = tmpDirtyComponents;
14.683 - tmpDirtyComponents = dirtyComponents;
14.684 - dirtyComponents = tmp;
14.685 - dirtyComponents.clear();
14.686 - }
14.687 - paintDirtyRegions(tmpDirtyComponents);
14.688 + delegate.paintDirtyRegions();
14.689 }
14.690
14.691 - private void paintDirtyRegions(Map<Component,Rectangle>
14.692 - tmpDirtyComponents){
14.693 - int i, count;
14.694 - java.util.List<Component> roots;
14.695 - Component dirtyComponent;
14.696 -
14.697 - count = tmpDirtyComponents.size();
14.698 - if (count == 0) {
14.699 - return;
14.700 - }
14.701 -
14.702 - Rectangle rect;
14.703 - int localBoundsX = 0;
14.704 - int localBoundsY = 0;
14.705 - int localBoundsH;
14.706 - int localBoundsW;
14.707 - Enumeration keys;
14.708 -
14.709 - roots = new ArrayList<Component>(count);
14.710 -
14.711 - for (Component dirty : tmpDirtyComponents.keySet()) {
14.712 - collectDirtyComponents(tmpDirtyComponents, dirty, roots);
14.713 - }
14.714 -
14.715 - count = roots.size();
14.716 - painting = true;
14.717 - try {
14.718 - for(i=0 ; i < count ; i++) {
14.719 - dirtyComponent = roots.get(i);
14.720 - rect = tmpDirtyComponents.get(dirtyComponent);
14.721 - localBoundsH = dirtyComponent.getHeight();
14.722 - localBoundsW = dirtyComponent.getWidth();
14.723 -
14.724 - SwingUtilities.computeIntersection(localBoundsX,
14.725 - localBoundsY,
14.726 - localBoundsW,
14.727 - localBoundsH,
14.728 - rect);
14.729 - if (dirtyComponent instanceof JComponent) {
14.730 - ((JComponent)dirtyComponent).paintImmediately(
14.731 - rect.x,rect.y,rect.width, rect.height);
14.732 - }
14.733 - else if (dirtyComponent.isShowing()) {
14.734 - Graphics g = JComponent.safelyGetGraphics(
14.735 - dirtyComponent, dirtyComponent);
14.736 - // If the Graphics goes away, it means someone disposed of
14.737 - // the window, don't do anything.
14.738 - if (g != null) {
14.739 - g.setClip(rect.x, rect.y, rect.width, rect.height);
14.740 - try {
14.741 - dirtyComponent.paint(g);
14.742 - } finally {
14.743 - g.dispose();
14.744 - }
14.745 - }
14.746 - }
14.747 - // If the repaintRoot has been set, service it now and
14.748 - // remove any components that are children of repaintRoot.
14.749 - if (repaintRoot != null) {
14.750 - adjustRoots(repaintRoot, roots, i + 1);
14.751 - count = roots.size();
14.752 - paintManager.isRepaintingRoot = true;
14.753 - repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
14.754 - repaintRoot.getHeight());
14.755 - paintManager.isRepaintingRoot = false;
14.756 - // Only service repaintRoot once.
14.757 - repaintRoot = null;
14.758 - }
14.759 - }
14.760 - } finally {
14.761 - painting = false;
14.762 - }
14.763 -
14.764 - updateWindows(tmpDirtyComponents);
14.765 -
14.766 - tmpDirtyComponents.clear();
14.767 - }
14.768 -
14.769 -
14.770 - /**
14.771 - * Removes any components from roots that are children of
14.772 - * root.
14.773 - */
14.774 - private void adjustRoots(JComponent root,
14.775 - java.util.List<Component> roots, int index) {
14.776 - for (int i = roots.size() - 1; i >= index; i--) {
14.777 - Component c = roots.get(i);
14.778 - for(;;) {
14.779 - if (c == root || c == null || !(c instanceof JComponent)) {
14.780 - break;
14.781 - }
14.782 - c = c.getParent();
14.783 - }
14.784 - if (c == root) {
14.785 - roots.remove(i);
14.786 - }
14.787 - }
14.788 - }
14.789 -
14.790 - Rectangle tmp = new Rectangle();
14.791 -
14.792 - void collectDirtyComponents(Map<Component,Rectangle> dirtyComponents,
14.793 - Component dirtyComponent,
14.794 - java.util.List<Component> roots) {
14.795 - int dx, dy, rootDx, rootDy;
14.796 - Component component, rootDirtyComponent,parent;
14.797 - Rectangle cBounds;
14.798 -
14.799 - // Find the highest parent which is dirty. When we get out of this
14.800 - // rootDx and rootDy will contain the translation from the
14.801 - // rootDirtyComponent's coordinate system to the coordinates of the
14.802 - // original dirty component. The tmp Rect is also used to compute the
14.803 - // visible portion of the dirtyRect.
14.804 -
14.805 - component = rootDirtyComponent = dirtyComponent;
14.806 -
14.807 - int x = dirtyComponent.getX();
14.808 - int y = dirtyComponent.getY();
14.809 - int w = dirtyComponent.getWidth();
14.810 - int h = dirtyComponent.getHeight();
14.811 -
14.812 - dx = rootDx = 0;
14.813 - dy = rootDy = 0;
14.814 - tmp.setBounds(dirtyComponents.get(dirtyComponent));
14.815 -
14.816 - // System.out.println("Collect dirty component for bound " + tmp +
14.817 - // "component bounds is " + cBounds);;
14.818 - SwingUtilities.computeIntersection(0,0,w,h,tmp);
14.819 -
14.820 - if (tmp.isEmpty()) {
14.821 - // System.out.println("Empty 1");
14.822 - return;
14.823 - }
14.824 -
14.825 - for(;;) {
14.826 - if(!(component instanceof JComponent))
14.827 - break;
14.828 -
14.829 - parent = component.getParent();
14.830 - if(parent == null)
14.831 - break;
14.832 -
14.833 - component = parent;
14.834 -
14.835 - dx += x;
14.836 - dy += y;
14.837 - tmp.setLocation(tmp.x + x, tmp.y + y);
14.838 -
14.839 - x = component.getX();
14.840 - y = component.getY();
14.841 - w = component.getWidth();
14.842 - h = component.getHeight();
14.843 - tmp = SwingUtilities.computeIntersection(0,0,w,h,tmp);
14.844 -
14.845 - if (tmp.isEmpty()) {
14.846 - // System.out.println("Empty 2");
14.847 - return;
14.848 - }
14.849 -
14.850 - if (dirtyComponents.get(component) != null) {
14.851 - rootDirtyComponent = component;
14.852 - rootDx = dx;
14.853 - rootDy = dy;
14.854 - }
14.855 - }
14.856 -
14.857 - if (dirtyComponent != rootDirtyComponent) {
14.858 - Rectangle r;
14.859 - tmp.setLocation(tmp.x + rootDx - dx,
14.860 - tmp.y + rootDy - dy);
14.861 - r = dirtyComponents.get(rootDirtyComponent);
14.862 - SwingUtilities.computeUnion(tmp.x,tmp.y,tmp.width,tmp.height,r);
14.863 - }
14.864 -
14.865 - // If we haven't seen this root before, then we need to add it to the
14.866 - // list of root dirty Views.
14.867 -
14.868 - if (!roots.contains(rootDirtyComponent))
14.869 - roots.add(rootDirtyComponent);
14.870 - }
14.871 -
14.872 -
14.873 /**
14.874 * Returns a string that displays and identifies this
14.875 * object's properties.
14.876 *
14.877 * @return a String representation of this object
14.878 */
14.879 - public synchronized String toString() {
14.880 - StringBuffer sb = new StringBuffer();
14.881 - if(dirtyComponents != null)
14.882 - sb.append("" + dirtyComponents);
14.883 - return sb.toString();
14.884 + public String toString() {
14.885 + return delegate.toString();
14.886 }
14.887
14.888
14.889 @@ -968,11 +276,7 @@
14.890 * repaint manager.
14.891 */
14.892 public Image getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) {
14.893 - RepaintManager delegate = getDelegate(c);
14.894 - if (delegate != null) {
14.895 - return delegate.getOffscreenBuffer(c, proposedWidth, proposedHeight);
14.896 - }
14.897 - return _getOffscreenBuffer(c, proposedWidth, proposedHeight);
14.898 + return delegate.getOffscreenBuffer(c, proposedWidth, proposedHeight);
14.899 }
14.900
14.901 /**
14.902 @@ -989,153 +293,20 @@
14.903 */
14.904 public Image getVolatileOffscreenBuffer(Component c,
14.905 int proposedWidth,int proposedHeight) {
14.906 - RepaintManager delegate = getDelegate(c);
14.907 - if (delegate != null) {
14.908 - return delegate.getVolatileOffscreenBuffer(c, proposedWidth,
14.909 - proposedHeight);
14.910 - }
14.911 -
14.912 - // If the window is non-opaque, it's double-buffered at peer's level
14.913 - Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
14.914 - if (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
14.915 - Toolkit tk = Toolkit.getDefaultToolkit();
14.916 - if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
14.917 - return null;
14.918 - }
14.919 - }
14.920 -
14.921 - GraphicsConfiguration config = c.getGraphicsConfiguration();
14.922 - if (config == null) {
14.923 - config = GraphicsEnvironment.getLocalGraphicsEnvironment().
14.924 - getDefaultScreenDevice().getDefaultConfiguration();
14.925 - }
14.926 - Dimension maxSize = getDoubleBufferMaximumSize();
14.927 - int width = proposedWidth < 1 ? 1 :
14.928 - (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
14.929 - int height = proposedHeight < 1 ? 1 :
14.930 - (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
14.931 - VolatileImage image = volatileMap.get(config);
14.932 - if (image == null || image.getWidth() < width ||
14.933 - image.getHeight() < height) {
14.934 - if (image != null) {
14.935 - image.flush();
14.936 - }
14.937 - image = config.createCompatibleVolatileImage(width, height);
14.938 - volatileMap.put(config, image);
14.939 - }
14.940 - return image;
14.941 + return delegate.getVolatileOffscreenBuffer(c, proposedWidth, proposedHeight);
14.942 }
14.943
14.944 - private Image _getOffscreenBuffer(Component c, int proposedWidth, int proposedHeight) {
14.945 - Dimension maxSize = getDoubleBufferMaximumSize();
14.946 - DoubleBufferInfo doubleBuffer;
14.947 - int width, height;
14.948 -
14.949 - // If the window is non-opaque, it's double-buffered at peer's level
14.950 - Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
14.951 - if (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
14.952 - Toolkit tk = Toolkit.getDefaultToolkit();
14.953 - if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
14.954 - return null;
14.955 - }
14.956 - }
14.957 -
14.958 - if (standardDoubleBuffer == null) {
14.959 - standardDoubleBuffer = new DoubleBufferInfo();
14.960 - }
14.961 - doubleBuffer = standardDoubleBuffer;
14.962 -
14.963 - width = proposedWidth < 1? 1 :
14.964 - (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
14.965 - height = proposedHeight < 1? 1 :
14.966 - (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
14.967 -
14.968 - if (doubleBuffer.needsReset || (doubleBuffer.image != null &&
14.969 - (doubleBuffer.size.width < width ||
14.970 - doubleBuffer.size.height < height))) {
14.971 - doubleBuffer.needsReset = false;
14.972 - if (doubleBuffer.image != null) {
14.973 - doubleBuffer.image.flush();
14.974 - doubleBuffer.image = null;
14.975 - }
14.976 - width = Math.max(doubleBuffer.size.width, width);
14.977 - height = Math.max(doubleBuffer.size.height, height);
14.978 - }
14.979 -
14.980 - Image result = doubleBuffer.image;
14.981 -
14.982 - if (doubleBuffer.image == null) {
14.983 - result = c.createImage(width , height);
14.984 - doubleBuffer.size = new Dimension(width, height);
14.985 - if (c instanceof JComponent) {
14.986 - ((JComponent)c).setCreatedDoubleBuffer(true);
14.987 - doubleBuffer.image = result;
14.988 - }
14.989 - // JComponent will inform us when it is no longer valid
14.990 - // (via removeNotify) we have no such hook to other components,
14.991 - // therefore we don't keep a ref to the Component
14.992 - // (indirectly through the Image) by stashing the image.
14.993 - }
14.994 - return result;
14.995 - }
14.996 -
14.997 -
14.998 /** Set the maximum double buffer size. **/
14.999 public void setDoubleBufferMaximumSize(Dimension d) {
14.1000 - doubleBufferMaxSize = d;
14.1001 - if (doubleBufferMaxSize == null) {
14.1002 - clearImages();
14.1003 - } else {
14.1004 - clearImages(d.width, d.height);
14.1005 - }
14.1006 + delegate.setDoubleBufferMaximumSize(d);
14.1007 }
14.1008 -
14.1009 - private void clearImages() {
14.1010 - clearImages(0, 0);
14.1011 - }
14.1012 -
14.1013 - private void clearImages(int width, int height) {
14.1014 - if (standardDoubleBuffer != null && standardDoubleBuffer.image != null) {
14.1015 - if (standardDoubleBuffer.image.getWidth(null) > width ||
14.1016 - standardDoubleBuffer.image.getHeight(null) > height) {
14.1017 - standardDoubleBuffer.image.flush();
14.1018 - standardDoubleBuffer.image = null;
14.1019 - }
14.1020 - }
14.1021 - // Clear out the VolatileImages
14.1022 - Iterator gcs = volatileMap.keySet().iterator();
14.1023 - while (gcs.hasNext()) {
14.1024 - GraphicsConfiguration gc = (GraphicsConfiguration)gcs.next();
14.1025 - VolatileImage image = volatileMap.get(gc);
14.1026 - if (image.getWidth() > width || image.getHeight() > height) {
14.1027 - image.flush();
14.1028 - gcs.remove();
14.1029 - }
14.1030 - }
14.1031 - }
14.1032 -
14.1033 /**
14.1034 * Returns the maximum double buffer size.
14.1035 *
14.1036 * @return a Dimension object representing the maximum size
14.1037 */
14.1038 public Dimension getDoubleBufferMaximumSize() {
14.1039 - if (doubleBufferMaxSize == null) {
14.1040 - try {
14.1041 - Rectangle virtualBounds = new Rectangle();
14.1042 - GraphicsEnvironment ge = GraphicsEnvironment.
14.1043 - getLocalGraphicsEnvironment();
14.1044 - for (GraphicsDevice gd : ge.getScreenDevices()) {
14.1045 - GraphicsConfiguration gc = gd.getDefaultConfiguration();
14.1046 - virtualBounds = virtualBounds.union(gc.getBounds());
14.1047 - }
14.1048 - doubleBufferMaxSize = new Dimension(virtualBounds.width,
14.1049 - virtualBounds.height);
14.1050 - } catch (HeadlessException e) {
14.1051 - doubleBufferMaxSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
14.1052 - }
14.1053 - }
14.1054 - return doubleBufferMaxSize;
14.1055 + return delegate.getDoubleBufferMaximumSize();
14.1056 }
14.1057
14.1058 /**
14.1059 @@ -1148,11 +319,7 @@
14.1060 * @see #isDoubleBufferingEnabled
14.1061 */
14.1062 public void setDoubleBufferingEnabled(boolean aFlag) {
14.1063 - doubleBufferingEnabled = aFlag;
14.1064 - PaintManager paintManager = getPaintManager();
14.1065 - if (!aFlag && paintManager.getClass() != PaintManager.class) {
14.1066 - setPaintManager(new PaintManager());
14.1067 - }
14.1068 + delegate.setDoubleBufferingEnabled(aFlag);
14.1069 }
14.1070
14.1071 /**
14.1072 @@ -1167,500 +334,6 @@
14.1073 * @return true if this object is double buffered
14.1074 */
14.1075 public boolean isDoubleBufferingEnabled() {
14.1076 - return doubleBufferingEnabled;
14.1077 - }
14.1078 -
14.1079 - /**
14.1080 - * This resets the double buffer. Actually, it marks the double buffer
14.1081 - * as invalid, the double buffer will then be recreated on the next
14.1082 - * invocation of getOffscreenBuffer.
14.1083 - */
14.1084 - void resetDoubleBuffer() {
14.1085 - if (standardDoubleBuffer != null) {
14.1086 - standardDoubleBuffer.needsReset = true;
14.1087 - }
14.1088 - }
14.1089 -
14.1090 - /**
14.1091 - * This resets the volatile double buffer.
14.1092 - */
14.1093 - void resetVolatileDoubleBuffer(GraphicsConfiguration gc) {
14.1094 - Image image = volatileMap.remove(gc);
14.1095 - if (image != null) {
14.1096 - image.flush();
14.1097 - }
14.1098 - }
14.1099 -
14.1100 - /**
14.1101 - * Returns true if we should use the <code>Image</code> returned
14.1102 - * from <code>getVolatileOffscreenBuffer</code> to do double buffering.
14.1103 - */
14.1104 - boolean useVolatileDoubleBuffer() {
14.1105 - return volatileImageBufferEnabled;
14.1106 - }
14.1107 -
14.1108 - /**
14.1109 - * Returns true if the current thread is the thread painting. This
14.1110 - * will return false if no threads are painting.
14.1111 - */
14.1112 - private synchronized boolean isPaintingThread() {
14.1113 - return (Thread.currentThread() == paintThread);
14.1114 - }
14.1115 - //
14.1116 - // Paint methods. You very, VERY rarely need to invoke these.
14.1117 - // They are invoked directly from JComponent's painting code and
14.1118 - // when painting happens outside the normal flow: DefaultDesktopManager
14.1119 - // and JViewport. If you end up needing these methods in other places be
14.1120 - // careful that you don't get stuck in a paint loop.
14.1121 - //
14.1122 -
14.1123 - /**
14.1124 - * Paints a region of a component
14.1125 - *
14.1126 - * @param paintingComponent Component to paint
14.1127 - * @param bufferComponent Component to obtain buffer for
14.1128 - * @param g Graphics to paint to
14.1129 - * @param x X-coordinate
14.1130 - * @param y Y-coordinate
14.1131 - * @param w Width
14.1132 - * @param h Height
14.1133 - */
14.1134 - void paint(JComponent paintingComponent,
14.1135 - JComponent bufferComponent, Graphics g,
14.1136 - int x, int y, int w, int h) {
14.1137 - PaintManager paintManager = getPaintManager();
14.1138 - if (!isPaintingThread()) {
14.1139 - // We're painting to two threads at once. PaintManager deals
14.1140 - // with this a bit better than BufferStrategyPaintManager, use
14.1141 - // it to avoid possible exceptions/corruption.
14.1142 - if (paintManager.getClass() != PaintManager.class) {
14.1143 - paintManager = new PaintManager();
14.1144 - paintManager.repaintManager = this;
14.1145 - }
14.1146 - }
14.1147 - if (!paintManager.paint(paintingComponent, bufferComponent, g,
14.1148 - x, y, w, h)) {
14.1149 - g.setClip(x, y, w, h);
14.1150 - paintingComponent.paintToOffscreen(g, x, y, w, h, x + w, y + h);
14.1151 - }
14.1152 - }
14.1153 -
14.1154 - /**
14.1155 - * Does a copy area on the specified region.
14.1156 - *
14.1157 - * @param clip Whether or not the copyArea needs to be clipped to the
14.1158 - * Component's bounds.
14.1159 - */
14.1160 - void copyArea(JComponent c, Graphics g, int x, int y, int w, int h,
14.1161 - int deltaX, int deltaY, boolean clip) {
14.1162 - getPaintManager().copyArea(c, g, x, y, w, h, deltaX, deltaY, clip);
14.1163 - }
14.1164 -
14.1165 - /**
14.1166 - * Invoked prior to any paint/copyArea method calls. This will
14.1167 - * be followed by an invocation of <code>endPaint</code>.
14.1168 - * <b>WARNING</b>: Callers of this method need to wrap the call
14.1169 - * in a <code>try/finally</code>, otherwise if an exception is thrown
14.1170 - * during the course of painting the RepaintManager may
14.1171 - * be left in a state in which the screen is not updated, eg:
14.1172 - * <pre>
14.1173 - * repaintManager.beginPaint();
14.1174 - * try {
14.1175 - * repaintManager.paint(...);
14.1176 - * } finally {
14.1177 - * repaintManager.endPaint();
14.1178 - * }
14.1179 - * </pre>
14.1180 - */
14.1181 - void beginPaint() {
14.1182 - boolean multiThreadedPaint = false;
14.1183 - int paintDepth;
14.1184 - Thread currentThread = Thread.currentThread();
14.1185 - synchronized(this) {
14.1186 - paintDepth = this.paintDepth;
14.1187 - if (paintThread == null || currentThread == paintThread) {
14.1188 - paintThread = currentThread;
14.1189 - this.paintDepth++;
14.1190 - } else {
14.1191 - multiThreadedPaint = true;
14.1192 - }
14.1193 - }
14.1194 - if (!multiThreadedPaint && paintDepth == 0) {
14.1195 - getPaintManager().beginPaint();
14.1196 - }
14.1197 - }
14.1198 -
14.1199 - /**
14.1200 - * Invoked after <code>beginPaint</code> has been invoked.
14.1201 - */
14.1202 - void endPaint() {
14.1203 - if (isPaintingThread()) {
14.1204 - PaintManager paintManager = null;
14.1205 - synchronized(this) {
14.1206 - if (--paintDepth == 0) {
14.1207 - paintManager = getPaintManager();
14.1208 - }
14.1209 - }
14.1210 - if (paintManager != null) {
14.1211 - paintManager.endPaint();
14.1212 - synchronized(this) {
14.1213 - paintThread = null;
14.1214 - }
14.1215 - }
14.1216 - }
14.1217 - }
14.1218 -
14.1219 - /**
14.1220 - * If possible this will show a previously rendered portion of
14.1221 - * a Component. If successful, this will return true, otherwise false.
14.1222 - * <p>
14.1223 - * WARNING: This method is invoked from the native toolkit thread, be
14.1224 - * very careful as to what methods this invokes!
14.1225 - */
14.1226 - boolean show(Container c, int x, int y, int w, int h) {
14.1227 - return getPaintManager().show(c, x, y, w, h);
14.1228 - }
14.1229 -
14.1230 - /**
14.1231 - * Invoked when the doubleBuffered or useTrueDoubleBuffering
14.1232 - * properties of a JRootPane change. This may come in on any thread.
14.1233 - */
14.1234 - void doubleBufferingChanged(JRootPane rootPane) {
14.1235 - getPaintManager().doubleBufferingChanged(rootPane);
14.1236 - }
14.1237 -
14.1238 - /**
14.1239 - * Sets the <code>PaintManager</code> that is used to handle all
14.1240 - * double buffered painting.
14.1241 - *
14.1242 - * @param paintManager The PaintManager to use. Passing in null indicates
14.1243 - * the fallback PaintManager should be used.
14.1244 - */
14.1245 - void setPaintManager(PaintManager paintManager) {
14.1246 - if (paintManager == null) {
14.1247 - paintManager = new PaintManager();
14.1248 - }
14.1249 - PaintManager oldPaintManager;
14.1250 - synchronized(this) {
14.1251 - oldPaintManager = this.paintManager;
14.1252 - this.paintManager = paintManager;
14.1253 - paintManager.repaintManager = this;
14.1254 - }
14.1255 - if (oldPaintManager != null) {
14.1256 - oldPaintManager.dispose();
14.1257 - }
14.1258 - }
14.1259 -
14.1260 - private synchronized PaintManager getPaintManager() {
14.1261 - if (paintManager == null) {
14.1262 - PaintManager paintManager = null;
14.1263 - if (doubleBufferingEnabled && !nativeDoubleBuffering) {
14.1264 - switch (bufferStrategyType) {
14.1265 - case BUFFER_STRATEGY_NOT_SPECIFIED:
14.1266 - Toolkit tk = Toolkit.getDefaultToolkit();
14.1267 - if (tk instanceof SunToolkit) {
14.1268 - SunToolkit stk = (SunToolkit) tk;
14.1269 - if (stk.useBufferPerWindow()) {
14.1270 - paintManager = new BufferStrategyPaintManager();
14.1271 - }
14.1272 - }
14.1273 - break;
14.1274 - case BUFFER_STRATEGY_SPECIFIED_ON:
14.1275 - paintManager = new BufferStrategyPaintManager();
14.1276 - break;
14.1277 - default:
14.1278 - break;
14.1279 - }
14.1280 - }
14.1281 - // null case handled in setPaintManager
14.1282 - setPaintManager(paintManager);
14.1283 - }
14.1284 - return paintManager;
14.1285 - }
14.1286 -
14.1287 - private void scheduleProcessingRunnable() {
14.1288 - scheduleProcessingRunnable(AppContext.getAppContext());
14.1289 - }
14.1290 -
14.1291 - private void scheduleProcessingRunnable(AppContext context) {
14.1292 - if (processingRunnable.markPending()) {
14.1293 - Toolkit tk = Toolkit.getDefaultToolkit();
14.1294 - if (tk instanceof SunToolkit) {
14.1295 - SunToolkit.getSystemEventQueueImplPP(context).
14.1296 - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
14.1297 - processingRunnable));
14.1298 - } else {
14.1299 - Toolkit.getDefaultToolkit().getSystemEventQueue().
14.1300 - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
14.1301 - processingRunnable));
14.1302 - }
14.1303 - }
14.1304 - }
14.1305 -
14.1306 -
14.1307 - /**
14.1308 - * PaintManager is used to handle all double buffered painting for
14.1309 - * Swing. Subclasses should call back into the JComponent method
14.1310 - * <code>paintToOffscreen</code> to handle the actual painting.
14.1311 - */
14.1312 - static class PaintManager {
14.1313 - /**
14.1314 - * RepaintManager the PaintManager has been installed on.
14.1315 - */
14.1316 - protected RepaintManager repaintManager;
14.1317 - boolean isRepaintingRoot;
14.1318 -
14.1319 - /**
14.1320 - * Paints a region of a component
14.1321 - *
14.1322 - * @param paintingComponent Component to paint
14.1323 - * @param bufferComponent Component to obtain buffer for
14.1324 - * @param g Graphics to paint to
14.1325 - * @param x X-coordinate
14.1326 - * @param y Y-coordinate
14.1327 - * @param w Width
14.1328 - * @param h Height
14.1329 - * @return true if painting was successful.
14.1330 - */
14.1331 - public boolean paint(JComponent paintingComponent,
14.1332 - JComponent bufferComponent, Graphics g,
14.1333 - int x, int y, int w, int h) {
14.1334 - // First attempt to use VolatileImage buffer for performance.
14.1335 - // If this fails (which should rarely occur), fallback to a
14.1336 - // standard Image buffer.
14.1337 - boolean paintCompleted = false;
14.1338 - Image offscreen;
14.1339 - if (repaintManager.useVolatileDoubleBuffer() &&
14.1340 - (offscreen = getValidImage(repaintManager.
14.1341 - getVolatileOffscreenBuffer(bufferComponent, w, h))) != null) {
14.1342 - VolatileImage vImage = (java.awt.image.VolatileImage)offscreen;
14.1343 - GraphicsConfiguration gc = bufferComponent.
14.1344 - getGraphicsConfiguration();
14.1345 - for (int i = 0; !paintCompleted &&
14.1346 - i < RepaintManager.VOLATILE_LOOP_MAX; i++) {
14.1347 - if (vImage.validate(gc) ==
14.1348 - VolatileImage.IMAGE_INCOMPATIBLE) {
14.1349 - repaintManager.resetVolatileDoubleBuffer(gc);
14.1350 - offscreen = repaintManager.getVolatileOffscreenBuffer(
14.1351 - bufferComponent,w, h);
14.1352 - vImage = (java.awt.image.VolatileImage)offscreen;
14.1353 - }
14.1354 - paintDoubleBuffered(paintingComponent, vImage, g, x, y,
14.1355 - w, h);
14.1356 - paintCompleted = !vImage.contentsLost();
14.1357 - }
14.1358 - }
14.1359 - // VolatileImage painting loop failed, fallback to regular
14.1360 - // offscreen buffer
14.1361 - if (!paintCompleted && (offscreen = getValidImage(
14.1362 - repaintManager.getOffscreenBuffer(
14.1363 - bufferComponent, w, h))) != null) {
14.1364 - paintDoubleBuffered(paintingComponent, offscreen, g, x, y, w,
14.1365 - h);
14.1366 - paintCompleted = true;
14.1367 - }
14.1368 - return paintCompleted;
14.1369 - }
14.1370 -
14.1371 - /**
14.1372 - * Does a copy area on the specified region.
14.1373 - */
14.1374 - public void copyArea(JComponent c, Graphics g, int x, int y, int w,
14.1375 - int h, int deltaX, int deltaY, boolean clip) {
14.1376 - g.copyArea(x, y, w, h, deltaX, deltaY);
14.1377 - }
14.1378 -
14.1379 - /**
14.1380 - * Invoked prior to any calls to paint or copyArea.
14.1381 - */
14.1382 - public void beginPaint() {
14.1383 - }
14.1384 -
14.1385 - /**
14.1386 - * Invoked to indicate painting has been completed.
14.1387 - */
14.1388 - public void endPaint() {
14.1389 - }
14.1390 -
14.1391 - /**
14.1392 - * Shows a region of a previously rendered component. This
14.1393 - * will return true if successful, false otherwise. The default
14.1394 - * implementation returns false.
14.1395 - */
14.1396 - public boolean show(Container c, int x, int y, int w, int h) {
14.1397 - return false;
14.1398 - }
14.1399 -
14.1400 - /**
14.1401 - * Invoked when the doubleBuffered or useTrueDoubleBuffering
14.1402 - * properties of a JRootPane change. This may come in on any thread.
14.1403 - */
14.1404 - public void doubleBufferingChanged(JRootPane rootPane) {
14.1405 - }
14.1406 -
14.1407 - /**
14.1408 - * Paints a portion of a component to an offscreen buffer.
14.1409 - */
14.1410 - protected void paintDoubleBuffered(JComponent c, Image image,
14.1411 - Graphics g, int clipX, int clipY,
14.1412 - int clipW, int clipH) {
14.1413 - Graphics osg = image.getGraphics();
14.1414 - int bw = Math.min(clipW, image.getWidth(null));
14.1415 - int bh = Math.min(clipH, image.getHeight(null));
14.1416 - int x,y,maxx,maxy;
14.1417 -
14.1418 - try {
14.1419 - for(x = clipX, maxx = clipX+clipW; x < maxx ; x += bw ) {
14.1420 - for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) {
14.1421 - osg.translate(-x, -y);
14.1422 - osg.setClip(x,y,bw,bh);
14.1423 - c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy);
14.1424 - g.setClip(x, y, bw, bh);
14.1425 - g.drawImage(image, x, y, c);
14.1426 - osg.translate(x, y);
14.1427 - }
14.1428 - }
14.1429 - } finally {
14.1430 - osg.dispose();
14.1431 - }
14.1432 - }
14.1433 -
14.1434 - /**
14.1435 - * If <code>image</code> is non-null with a positive size it
14.1436 - * is returned, otherwise null is returned.
14.1437 - */
14.1438 - private Image getValidImage(Image image) {
14.1439 - if (image != null && image.getWidth(null) > 0 &&
14.1440 - image.getHeight(null) > 0) {
14.1441 - return image;
14.1442 - }
14.1443 - return null;
14.1444 - }
14.1445 -
14.1446 - /**
14.1447 - * Schedules a repaint for the specified component. This differs
14.1448 - * from <code>root.repaint</code> in that if the RepaintManager is
14.1449 - * currently processing paint requests it'll process this request
14.1450 - * with the current set of requests.
14.1451 - */
14.1452 - protected void repaintRoot(JComponent root) {
14.1453 - assert (repaintManager.repaintRoot == null);
14.1454 - if (repaintManager.painting) {
14.1455 - repaintManager.repaintRoot = root;
14.1456 - }
14.1457 - else {
14.1458 - root.repaint();
14.1459 - }
14.1460 - }
14.1461 -
14.1462 - /**
14.1463 - * Returns true if the component being painted is the root component
14.1464 - * that was previously passed to <code>repaintRoot</code>.
14.1465 - */
14.1466 - protected boolean isRepaintingRoot() {
14.1467 - return isRepaintingRoot;
14.1468 - }
14.1469 -
14.1470 - /**
14.1471 - * Cleans up any state. After invoked the PaintManager will no
14.1472 - * longer be used anymore.
14.1473 - */
14.1474 - protected void dispose() {
14.1475 - }
14.1476 - }
14.1477 -
14.1478 -
14.1479 - private class DoubleBufferInfo {
14.1480 - public Image image;
14.1481 - public Dimension size;
14.1482 - public boolean needsReset = false;
14.1483 - }
14.1484 -
14.1485 -
14.1486 - /**
14.1487 - * Listener installed to detect display changes. When display changes,
14.1488 - * schedules a callback to notify all RepaintManagers of the display
14.1489 - * changes. Only one DisplayChangedHandler is ever installed. The
14.1490 - * singleton instance will schedule notification for all AppContexts.
14.1491 - */
14.1492 - private static final class DisplayChangedHandler implements
14.1493 - DisplayChangedListener {
14.1494 - public void displayChanged() {
14.1495 - scheduleDisplayChanges();
14.1496 - }
14.1497 -
14.1498 - public void paletteChanged() {
14.1499 - }
14.1500 -
14.1501 - private void scheduleDisplayChanges() {
14.1502 - // To avoid threading problems, we notify each RepaintManager
14.1503 - // on the thread it was created on.
14.1504 - for (Object c : AppContext.getAppContexts()) {
14.1505 - AppContext context = (AppContext) c;
14.1506 - synchronized(context) {
14.1507 - if (!context.isDisposed()) {
14.1508 - EventQueue eventQueue = (EventQueue)context.get(
14.1509 - AppContext.EVENT_QUEUE_KEY);
14.1510 - if (eventQueue != null) {
14.1511 - eventQueue.postEvent(new InvocationEvent(
14.1512 - Toolkit.getDefaultToolkit(),
14.1513 - new DisplayChangedRunnable()));
14.1514 - }
14.1515 - }
14.1516 - }
14.1517 - }
14.1518 - }
14.1519 - }
14.1520 -
14.1521 -
14.1522 - private static final class DisplayChangedRunnable implements Runnable {
14.1523 - public void run() {
14.1524 - RepaintManager.currentManager((JComponent)null).displayChanged();
14.1525 - }
14.1526 - }
14.1527 -
14.1528 -
14.1529 - /**
14.1530 - * Runnable used to process all repaint/revalidate requests.
14.1531 - */
14.1532 - private final class ProcessingRunnable implements Runnable {
14.1533 - // If true, we're wainting on the EventQueue.
14.1534 - private boolean pending;
14.1535 -
14.1536 - /**
14.1537 - * Marks this processing runnable as pending. If this was not
14.1538 - * already marked as pending, true is returned.
14.1539 - */
14.1540 - public synchronized boolean markPending() {
14.1541 - if (!pending) {
14.1542 - pending = true;
14.1543 - return true;
14.1544 - }
14.1545 - return false;
14.1546 - }
14.1547 -
14.1548 - public void run() {
14.1549 - synchronized (this) {
14.1550 - pending = false;
14.1551 - }
14.1552 - // First pass, flush any heavy paint events into real paint
14.1553 - // events. If there are pending heavy weight requests this will
14.1554 - // result in q'ing this request up one more time. As
14.1555 - // long as no other requests come in between now and the time
14.1556 - // the second one is processed nothing will happen. This is not
14.1557 - // ideal, but the logic needed to suppress the second request is
14.1558 - // more headache than it's worth.
14.1559 - scheduleHeavyWeightPaints();
14.1560 - // Do the actual validation and painting.
14.1561 - validateInvalidComponents();
14.1562 - prePaintDirtyRegions();
14.1563 - }
14.1564 - }
14.1565 - private RepaintManager getDelegate(Component c) {
14.1566 - RepaintManager delegate = SwingUtilities3.getDelegateRepaintManager(c);
14.1567 - if (this == delegate) {
14.1568 - delegate = null;
14.1569 - }
14.1570 - return delegate;
14.1571 + return delegate.isDoubleBufferingEnabled();
14.1572 }
14.1573 }
15.1 --- a/src/share/classes/javax/swing/SwingPaintEventDispatcher.java Fri Jun 19 21:46:14 2009 +0200
15.2 +++ b/src/share/classes/javax/swing/SwingPaintEventDispatcher.java Sat Jun 20 22:10:34 2009 +0200
15.3 @@ -38,7 +38,7 @@
15.4 /**
15.5 * Swing's PaintEventDispatcher. If the component specified by the PaintEvent
15.6 * is a top level Swing component (JFrame, JWindow, JDialog, JApplet), this
15.7 - * will forward the request to the RepaintManager for eventual painting.
15.8 + * will forward the request to the RepaintController for eventual painting.
15.9 *
15.10 */
15.11 class SwingPaintEventDispatcher extends sun.awt.PaintEventDispatcher {
15.12 @@ -56,7 +56,7 @@
15.13 int w, int h) {
15.14 if (component instanceof RootPaneContainer) {
15.15 AppContext appContext = SunToolkit.targetToAppContext(component);
15.16 - RepaintManager rm = RepaintManager.currentManager(appContext);
15.17 + RepaintController rm = RepaintController.currentManager(appContext);
15.18 if (!SHOW_FROM_DOUBLE_BUFFER ||
15.19 !rm.show((Container)component, x, y, w, h)) {
15.20 rm.nativeAddDirtyRegion(appContext, (Container)component,
15.21 @@ -69,7 +69,7 @@
15.22 }
15.23 else if (component instanceof SwingHeavyWeight) {
15.24 AppContext appContext = SunToolkit.targetToAppContext(component);
15.25 - RepaintManager rm = RepaintManager.currentManager(appContext);
15.26 + RepaintController rm = RepaintController.currentManager(appContext);
15.27 rm.nativeAddDirtyRegion(appContext, (Container)component,
15.28 x, y, w, h);
15.29 return new IgnorePaintEvent(component, PaintEvent.PAINT,
15.30 @@ -85,7 +85,7 @@
15.31 public boolean queueSurfaceDataReplacing(Component c, Runnable r) {
15.32 if (c instanceof RootPaneContainer) {
15.33 AppContext appContext = SunToolkit.targetToAppContext(c);
15.34 - RepaintManager.currentManager(appContext).
15.35 + RepaintController.currentManager(appContext).
15.36 nativeQueueSurfaceDataRunnable(appContext, c, r);
15.37 return true;
15.38 }
16.1 --- a/src/share/classes/javax/swing/UIManager.java Fri Jun 19 21:46:14 2009 +0200
16.2 +++ b/src/share/classes/javax/swing/UIManager.java Sat Jun 20 22:10:34 2009 +0200
16.3 @@ -1446,7 +1446,7 @@
16.4 }
16.5
16.6 // Install Swing's PaintEventDispatcher
16.7 - if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {
16.8 + if (RepaintController.HANDLE_TOP_LEVEL_PAINT) {
16.9 sun.awt.PaintEventDispatcher.setPaintEventDispatcher(
16.10 new SwingPaintEventDispatcher());
16.11 }