FileDocCategorySizeDatePackage
RepaintManager.javaAPI DocJava SE 6 API53010Tue Jun 10 00:26:40 BST 2008javax.swing

RepaintManager

public class RepaintManager extends Object
This class manages repaint requests, allowing the number of repaints to be minimized, for example by collapsing multiple requests into a single repaint for members of a component tree.

As of 1.6 RepaintManager handles repaint requests for Swing's top level components (JApplet, JWindow, JFrame and JDialog). Any calls to repaint on one of these will call into the appropriate addDirtyRegion method.

version
1.70 10/17/06
author
Arnaud Weber

Fields Summary
static final boolean
HANDLE_TOP_LEVEL_PAINT
Whether or not the RepaintManager should handle paint requests for top levels.
private static final short
BUFFER_STRATEGY_NOT_SPECIFIED
private static final short
BUFFER_STRATEGY_SPECIFIED_ON
private static final short
BUFFER_STRATEGY_SPECIFIED_OFF
private static final short
BUFFER_STRATEGY_TYPE
private Map
volatileMap
Maps from GraphicsConfiguration to VolatileImage.
private Map
hwDirtyComponents
private Map
dirtyComponents
private Map
tmpDirtyComponents
private List
invalidComponents
private List
runnableList
boolean
doubleBufferingEnabled
private Dimension
doubleBufferMaxSize
DoubleBufferInfo
standardDoubleBuffer
private PaintManager
paintManager
Object responsible for hanlding core paint functionality.
private static final Object
repaintManagerKey
static boolean
volatileImageBufferEnabled
private static boolean
nativeDoubleBuffering
Value of the system property awt.nativeDoubleBuffering.
private static final int
VOLATILE_LOOP_MAX
private int
paintDepth
Number of beginPaint that have been invoked.
private short
bufferStrategyType
Type of buffer strategy to use. Will be one of the BUFFER_STRATEGY_ constants.
private boolean
painting
True if we're in the process of painting the dirty regions. This is set to true in paintDirtyRegions.
private JComponent
repaintRoot
If the PaintManager calls into repaintRoot during painting this field will be set to the root.
private Thread
paintThread
The Thread that has initiated painting. If null it indicates painting is not currently in progress.
Rectangle
tmp
Constructors Summary
public RepaintManager()
Create a new RepaintManager instance. You rarely call this constructor. directly. To get the default RepaintManager, use RepaintManager.currentManager(JComponent) (normally "this").

        // Because we can't know what a subclass is doing with the
        // volatile image we immediately punt in subclasses.  If this
        // poses a problem we'll need a more sophisticated detection algorithm,
        // or API.
        this(BUFFER_STRATEGY_SPECIFIED_OFF);
    
private RepaintManager(short bufferStrategyType)

        // If native doublebuffering is being used, do NOT use
        // Swing doublebuffering.
        doubleBufferingEnabled = !nativeDoubleBuffering;
        synchronized(this) {
            dirtyComponents = new IdentityHashMap<Component,Rectangle>();
            tmpDirtyComponents = new IdentityHashMap<Component,Rectangle>();
            this.bufferStrategyType = bufferStrategyType;
            hwDirtyComponents = new IdentityHashMap<Container,Rectangle>();
        }
    
Methods Summary
private java.awt.Image_getOffscreenBuffer(java.awt.Component c, int proposedWidth, int proposedHeight)

	Dimension maxSize = getDoubleBufferMaximumSize();
	DoubleBufferInfo doubleBuffer = null;
        int width, height;

        if (standardDoubleBuffer == null) {
            standardDoubleBuffer = new DoubleBufferInfo();
        }
        doubleBuffer = standardDoubleBuffer;
	    
	width = proposedWidth < 1? 1 : 
	          (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
        height = proposedHeight < 1? 1 : 
                  (proposedHeight > maxSize.height? maxSize.height : proposedHeight);

        if (doubleBuffer.needsReset || (doubleBuffer.image != null &&
                                        (doubleBuffer.size.width < width ||
                                         doubleBuffer.size.height < height))) {
            doubleBuffer.needsReset = false;
            if (doubleBuffer.image != null) {
                doubleBuffer.image.flush();
                doubleBuffer.image = null;
            }
            width = Math.max(doubleBuffer.size.width, width);
            height = Math.max(doubleBuffer.size.height, height);
        }

	Image result = doubleBuffer.image;

	if (doubleBuffer.image == null) {
            result = c.createImage(width , height);
            doubleBuffer.size = new Dimension(width, height);
	    if (c instanceof JComponent) {
		((JComponent)c).setCreatedDoubleBuffer(true);
		doubleBuffer.image = result;
	    }
	    // JComponent will inform us when it is no longer valid
	    // (via removeNotify) we have no such hook to other components,
	    // therefore we don't keep a ref to the Component
	    // (indirectly through the Image) by stashing the image.
	}
        return result;
    
public voidaddDirtyRegion(javax.swing.JComponent c, int x, int y, int w, int h)
Add a component in the list of components that should be refreshed. If c already has a dirty region, the rectangle (x,y,w,h) will be unioned with the region that should be redrawn.

param
c Component to repaint, null results in nothing happening.
param
x X coordinate of the region to repaint
param
y Y coordinate of the region to repaint
param
w Width of the region to repaint
param
h Height of the region to repaint
see
JComponent#repaint

        addDirtyRegion0(c, x, y, w, h);
    
public voidaddDirtyRegion(java.awt.Window window, int x, int y, int w, int h)
Adds window to the list of Components that need to be repainted.

param
window Window to repaint, null results in nothing happening.
param
x X coordinate of the region to repaint
param
y Y coordinate of the region to repaint
param
w Width of the region to repaint
param
h Height of the region to repaint
see
JFrame#repaint
see
JWindow#repaint
see
JDialog#repaint
since
1.6

        addDirtyRegion0(window, x, y, w, h);
    
public voidaddDirtyRegion(java.applet.Applet applet, int x, int y, int w, int h)
Adds applet to the list of Components that need to be repainted.

param
applet Applet to repaint, null results in nothing happening.
param
x X coordinate of the region to repaint
param
y Y coordinate of the region to repaint
param
w Width of the region to repaint
param
h Height of the region to repaint
see
JApplet#repaint
since
1.6

        addDirtyRegion0(applet, x, y, w, h);
    
private voidaddDirtyRegion0(java.awt.Container c, int x, int y, int w, int h)
Add a component in the list of components that should be refreshed. If c already has a dirty region, the rectangle (x,y,w,h) will be unioned with the region that should be redrawn.

see
JComponent#repaint

	/* Special cases we don't have to bother with.
	 */
        if ((w <= 0) || (h <= 0) || (c == null)) {
            return;
        }

	if ((c.getWidth() <= 0) || (c.getHeight() <= 0)) {
	    return;
	}

        if (extendDirtyRegion(c, x, y, w, h)) {
            // Component was already marked as dirty, region has been
            // extended, no need to continue.
            return;
        }

	/* Make sure that c and all it ancestors (up to an Applet or
	 * Window) are visible.  This loop has the same effect as 
	 * checking c.isShowing() (and note that it's still possible 
	 * that c is completely obscured by an opaque ancestor in 
	 * the specified rectangle).
	 */
	Component root = null;

        // Note: We can't synchronize around this, Frame.getExtendedState
        // is synchronized so that if we were to synchronize around this
        // it could lead to the possibility of getting locks out
        // of order and deadlocking.
	for (Container p = c; p != null; p = p.getParent()) {
	    if (!p.isVisible() || (p.getPeer() == null)) {
		return;
	    }
	    if ((p instanceof Window) || (p instanceof Applet)) {
                // Iconified frames are still visible!
                if (p instanceof Frame &&
                        (((Frame)p).getExtendedState() & Frame.ICONIFIED) ==
                                    Frame.ICONIFIED) {
                    return;
                }
		root = p;
		break;
	    }
	}

	if (root == null) return;

        synchronized(this) {
            if (extendDirtyRegion(c, x, y, w, h)) {
                // In between last check and this check another thread
                // queued up runnable, can bail here.
                return;
            }
            dirtyComponents.put(c, new Rectangle(x, y, w, h));
        }

	/* Queues a Runnable that calls validateInvalidComponents() and
	 * rm.paintDirtyRegions() with SwingUtilities.invokeLater().
	 */
	SystemEventQueueUtilities.queueComponentWorkRequest(root);
    
public synchronized voidaddInvalidComponent(javax.swing.JComponent invalidComponent)
Mark the component as in need of layout and queue a runnable for the event dispatching thread that will validate the components first isValidateRoot() ancestor.

see
JComponent#isValidateRoot
see
#removeInvalidComponent

        Component validateRoot = null;

	/* Find the first JComponent ancestor of this component whose
	 * isValidateRoot() method returns true.  
	 */
        for(Component c = invalidComponent; c != null; c = c.getParent()) {
	    if ((c instanceof CellRendererPane) || (c.getPeer() == null)) {
		return;
	    }
	    if ((c instanceof JComponent) && (((JComponent)c).isValidateRoot())) {
		validateRoot = c;
		break;
	    }
	}
        
	/* There's no validateRoot to apply validate to, so we're done.
	 */
	if (validateRoot == null) {
	    return;
	}

	/* If the validateRoot and all of its ancestors aren't visible
	 * then we don't do anything.  While we're walking up the tree
	 * we find the root Window or Applet.
	 */
	Component root = null;
	
	for(Component c = validateRoot; c != null; c = c.getParent()) {
	    if (!c.isVisible() || (c.getPeer() == null)) {
		return;
	    }
	    if ((c instanceof Window) || (c instanceof Applet)) {
		root = c;
		break;
	    }
	}

	if (root == null) {
	    return;
	}
	   
	/* Lazily create the invalidateComponents vector and add the
	 * validateRoot if it's not there already.  If this validateRoot
	 * is already in the vector, we're done.
	 */
	if (invalidComponents == null) {
	    invalidComponents = new ArrayList<Component>();
	}
	else {
	    int n = invalidComponents.size();
	    for(int i = 0; i < n; i++) {
		if(validateRoot == invalidComponents.get(i)) {
		    return;
		}
	    }
	}
	invalidComponents.add(validateRoot);

	/* Queues a Runnable that calls RepaintManager.validateInvalidComponents() 
	 * and RepaintManager.paintDirtyRegions() with SwingUtilities.invokeLater().
	 */
	SystemEventQueueUtilities.queueComponentWorkRequest(root);
    
private voidadjustRoots(javax.swing.JComponent root, java.util.List roots, int index)
Removes any components from roots that are children of root.

        for (int i = roots.size() - 1; i >= index; i--) {
            Component c = roots.get(i);
            for(;;) {
                if (c == root || c == null || !(c instanceof JComponent)) {
                    break;
                }
                c = c.getParent();
            }
            if (c == root) {
                roots.remove(i);
            }
        }
    
voidbeginPaint()
Invoked prior to any paint/copyArea method calls. This will be followed by an invocation of endPaint. WARNING: Callers of this method need to wrap the call in a try/finally, otherwise if an exception is thrown during the course of painting the RepaintManager may be left in a state in which the screen is not updated, eg:
repaintManager.beginPaint();
try {
repaintManager.paint(...);
} finally {
repaintManager.endPaint();
}

        boolean multiThreadedPaint = false;
        int paintDepth = 0;
        Thread currentThread = Thread.currentThread();
        synchronized(this) {
            paintDepth = this.paintDepth;
            if (paintThread == null || currentThread == paintThread) {
                paintThread = currentThread;
                this.paintDepth++;
            } else {
                multiThreadedPaint = true;
            }
        }
        if (!multiThreadedPaint && paintDepth == 0) {
            getPaintManager().beginPaint();
        }
    
private voidclearImages()

        clearImages(0, 0);
    
private voidclearImages(int width, int height)

        if (standardDoubleBuffer != null && standardDoubleBuffer.image != null) {
            if (standardDoubleBuffer.image.getWidth(null) > width || 
                standardDoubleBuffer.image.getHeight(null) > height) {
                standardDoubleBuffer.image.flush();
                standardDoubleBuffer.image = null;
	    }
        }
        // Clear out the VolatileImages
        Iterator gcs = volatileMap.keySet().iterator();
        while (gcs.hasNext()) {
            GraphicsConfiguration gc = (GraphicsConfiguration)gcs.next();
            VolatileImage image = (VolatileImage)volatileMap.get(gc);
            if (image.getWidth() > width || image.getHeight() > height) {
                image.flush();
                gcs.remove();
	    }
	}	    
    
voidcollectDirtyComponents(java.util.Map dirtyComponents, java.awt.Component dirtyComponent, java.util.List roots)


      
				 
				  
        int dx, dy, rootDx, rootDy;
        Component component, rootDirtyComponent,parent;
        Rectangle cBounds;

        // Find the highest parent which is dirty.  When we get out of this
        // rootDx and rootDy will contain the translation from the
        // rootDirtyComponent's coordinate system to the coordinates of the
        // original dirty component.  The tmp Rect is also used to compute the
        // visible portion of the dirtyRect.

        component = rootDirtyComponent = dirtyComponent;

        int x = dirtyComponent.getX();
        int y = dirtyComponent.getY();
        int w = dirtyComponent.getWidth();
        int h = dirtyComponent.getHeight();

        dx = rootDx = 0;
        dy = rootDy = 0;
        tmp.setBounds((Rectangle) dirtyComponents.get(dirtyComponent));

        // System.out.println("Collect dirty component for bound " + tmp + 
        //                                   "component bounds is " + cBounds);;
        SwingUtilities.computeIntersection(0,0,w,h,tmp);

        if (tmp.isEmpty()) {
            // System.out.println("Empty 1");
            return;
        } 

        for(;;) {
            if(!(component instanceof JComponent))
                break;

            parent = component.getParent();
            if(parent == null) 
                break;

            component = parent;

            dx += x;
            dy += y;
            tmp.setLocation(tmp.x + x, tmp.y + y);

            x = component.getX();
            y = component.getY();
            w = component.getWidth();
            h = component.getHeight();
            tmp = SwingUtilities.computeIntersection(0,0,w,h,tmp);

            if (tmp.isEmpty()) {
                // System.out.println("Empty 2");
                return;
            }

            if (dirtyComponents.get(component) != null) {
                rootDirtyComponent = component;
                rootDx = dx;
                rootDy = dy;
            }
        } 

        if (dirtyComponent != rootDirtyComponent) {
	    Rectangle r;
            tmp.setLocation(tmp.x + rootDx - dx,
			    tmp.y + rootDy - dy);
	    r = (Rectangle)dirtyComponents.get(rootDirtyComponent);
	    SwingUtilities.computeUnion(tmp.x,tmp.y,tmp.width,tmp.height,r);
        }

        // If we haven't seen this root before, then we need to add it to the
        // list of root dirty Views.

        if (!roots.contains(rootDirtyComponent)) 
            roots.add(rootDirtyComponent);	
    
voidcopyArea(javax.swing.JComponent c, java.awt.Graphics g, int x, int y, int w, int h, int deltaX, int deltaY, boolean clip)
Does a copy area on the specified region.

param
clip Whether or not the copyArea needs to be clipped to the Component's bounds.

        getPaintManager().copyArea(c, g, x, y, w, h, deltaX, deltaY, clip);
    
public static javax.swing.RepaintManagercurrentManager(java.awt.Component c)
Return the RepaintManager for the calling thread given a Component.

param
c a Component -- unused in the default implementation, but could be used by an overridden version to return a different RepaintManager depending on the Component
return
the RepaintManager object



     
	volatileImageBufferEnabled = "true".equals(AccessController.
                doPrivileged(new GetPropertyAction(
                "swing.volatileImageBufferEnabled", "true")));
        boolean headless = GraphicsEnvironment.isHeadless();
        if (volatileImageBufferEnabled && headless) {
            volatileImageBufferEnabled = false;
        }
        nativeDoubleBuffering = "true".equals(AccessController.doPrivileged(
                    new GetPropertyAction("awt.nativeDoubleBuffering")));
	String bs = AccessController.doPrivileged(
                          new GetPropertyAction("swing.bufferPerWindow"));
        if (headless) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
        else if (bs == null) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_NOT_SPECIFIED;
        }
        else if ("true".equals(bs)) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_ON;
        }
        else {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
        HANDLE_TOP_LEVEL_PAINT = "true".equals(AccessController.doPrivileged(
               new GetPropertyAction("swing.handleTopLevelPaint", "true")));
        GraphicsEnvironment ge = GraphicsEnvironment.
                getLocalGraphicsEnvironment();
        if (ge instanceof SunGraphicsEnvironment) {
            ((SunGraphicsEnvironment)ge).addDisplayChangedListener(
                    new DisplayChangedHandler());
        }
    
        // Note: SystemEventQueueUtilities.ComponentWorkRequest and
        // DisplayChangedRunnable pass in null as the component, so if
        // component is ever used to determine the current
        // RepaintManager, SystemEventQueueUtilities and
        // DisplayChangedRunnable will need to be modified
        // accordingly.
        return currentManager(AppContext.getAppContext());
    
static javax.swing.RepaintManagercurrentManager(sun.awt.AppContext appContext)
Returns the RepaintManager for the specified AppContext. If a RepaintManager has not been created for the specified AppContext this will return null.

        RepaintManager rm = (RepaintManager)appContext.get(repaintManagerKey);
        if (rm == null) {
            rm = new RepaintManager(BUFFER_STRATEGY_TYPE);
            appContext.put(repaintManagerKey, rm);
        }
	return rm;
    
public static javax.swing.RepaintManagercurrentManager(javax.swing.JComponent c)
Return the RepaintManager for the calling thread given a JComponent.

Note: This method exists for backward binary compatibility with earlier versions of the Swing library. It simply returns the result returned by {@link #currentManager(Component)}.

param
c a JComponent -- unused
return
the RepaintManager object

	return currentManager((Component)c);
    
private voiddisplayChanged()

        clearImages();
    
voiddoubleBufferingChanged(javax.swing.JRootPane rootPane)
Invoked when the doubleBuffered or useTrueDoubleBuffering properties of a JRootPane change. This may come in on any thread.

        getPaintManager().doubleBufferingChanged(rootPane);
    
voidendPaint()
Invoked after beginPaint has been invoked.

        if (isPaintingThread()) {
            PaintManager paintManager = null;
            synchronized(this) {
                if (--paintDepth == 0) {
                    paintManager = getPaintManager();
                }
            }
            if (paintManager != null) {
                paintManager.endPaint();
                synchronized(this) {
                    paintThread = null;
                }
            }
        }
    
private synchronized booleanextendDirtyRegion(java.awt.Component c, int x, int y, int w, int h)
Extends the dirty region for the specified component to include the new region.

return
false if c is not yet marked dirty.

        Rectangle r = (Rectangle)dirtyComponents.get(c);
        if (r != null) {
            // A non-null r implies c is already marked as dirty,
            // and that the parent is valid. Therefore we can
            // just union the rect and bail.
            SwingUtilities.computeUnion(x, y, w, h, r);
            return true;
        }
        return false;
    
public java.awt.RectanglegetDirtyRegion(javax.swing.JComponent aComponent)
Return the current dirty region for a component. Return an empty rectangle if the component is not dirty.

	Rectangle r = null;
	synchronized(this) {
	    r = (Rectangle)dirtyComponents.get(aComponent);
	}
	if(r == null)
	    return new Rectangle(0,0,0,0);
	else
	    return new Rectangle(r);
    
public java.awt.DimensiongetDoubleBufferMaximumSize()
Returns the maximum double buffer size.

return
a Dimension object representing the maximum size

	if (doubleBufferMaxSize == null) {
	    try {
                Rectangle virtualBounds = new Rectangle();
                GraphicsEnvironment ge = GraphicsEnvironment.
                                                 getLocalGraphicsEnvironment();
                for (GraphicsDevice gd : ge.getScreenDevices()) {
                    GraphicsConfiguration gc = gd.getDefaultConfiguration();
                    virtualBounds = virtualBounds.union(gc.getBounds());
                }
	        doubleBufferMaxSize = new Dimension(virtualBounds.width,
                                                    virtualBounds.height);
	    } catch (HeadlessException e) {
		doubleBufferMaxSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
	    }
	}
        return doubleBufferMaxSize;
    
public java.awt.ImagegetOffscreenBuffer(java.awt.Component c, int proposedWidth, int proposedHeight)
Return the offscreen buffer that should be used as a double buffer with the component c. By default there is a double buffer per RepaintManager. The buffer might be smaller than (proposedWidth,proposedHeight) This happens when the maximum double buffer size as been set for the receiving repaint manager.

	return _getOffscreenBuffer(c, proposedWidth, proposedHeight);
    
private synchronized javax.swing.RepaintManager$PaintManagergetPaintManager()

        if (paintManager == null) {
            PaintManager paintManager = null;
            if (doubleBufferingEnabled && !nativeDoubleBuffering) {
                switch (bufferStrategyType) {
                case BUFFER_STRATEGY_NOT_SPECIFIED:
                    if (((SunToolkit)Toolkit.getDefaultToolkit()).
                                                useBufferPerWindow()) {
                        paintManager = new BufferStrategyPaintManager();
                    }
                    break;
                case BUFFER_STRATEGY_SPECIFIED_ON:
                    paintManager = new BufferStrategyPaintManager();
                    break;
                default:
                    break;
                }
            }
            // null case handled in setPaintManager
            setPaintManager(paintManager);
        }
        return paintManager;
    
public java.awt.ImagegetVolatileOffscreenBuffer(java.awt.Component c, int proposedWidth, int proposedHeight)
Return a volatile offscreen buffer that should be used as a double buffer with the specified component c. The image returned will be an instance of VolatileImage, or null if a VolatileImage object could not be instantiated. This buffer might be smaller than (proposedWidth,proposedHeight). This happens when the maximum double buffer size has been set for this repaint manager.

see
java.awt.image.VolatileImage
since
1.4

        GraphicsConfiguration config = c.getGraphicsConfiguration();
        if (config == null) {
            config = GraphicsEnvironment.getLocalGraphicsEnvironment().
                            getDefaultScreenDevice().getDefaultConfiguration();
        }
	Dimension maxSize = getDoubleBufferMaximumSize();
	int width = proposedWidth < 1 ? 1 :
            (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
        int height = proposedHeight < 1 ? 1 :
            (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
        VolatileImage image = volatileMap.get(config);
        if (image == null || image.getWidth() < width ||
                             image.getHeight() < height) {
            if (image != null) {
                image.flush();
            }
            image = config.createCompatibleVolatileImage(width, height);
            volatileMap.put(config, image);
        }
        return image;
    
public booleanisCompletelyDirty(javax.swing.JComponent aComponent)
Convenience method that returns true if aComponent will be completely painted during the next paintDirtyRegions(). If computing dirty regions is expensive for your component, use this method and avoid computing dirty region if it return true.

	Rectangle r;
	
	r = getDirtyRegion(aComponent);
	if(r.width == Integer.MAX_VALUE &&
	   r.height == Integer.MAX_VALUE)
	    return true;
	else
	    return false;
    
public booleanisDoubleBufferingEnabled()
Returns true if this RepaintManager is double buffered. The default value for this property may vary from platform to platform. On platforms where native double buffering is supported in the AWT, the default value will be false to avoid unnecessary buffering in Swing. On platforms where native double buffering is not supported, the default value will be true.

return
true if this object is double buffered

        return doubleBufferingEnabled;
    
private synchronized booleanisPaintingThread()
Returns true if the current thread is the thread painting. This will return false if no threads are painting.

        return (Thread.currentThread() == paintThread);
    
public voidmarkCompletelyClean(javax.swing.JComponent aComponent)
Mark a component completely clean. aComponent will not get painted during the next paintDirtyRegions() call.

	synchronized(this) {
		dirtyComponents.remove(aComponent);
	}
    
public voidmarkCompletelyDirty(javax.swing.JComponent aComponent)
Mark a component completely dirty. aComponent will be completely painted during the next paintDirtyRegions() call.

	addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE);
    
voidnativeAddDirtyRegion(sun.awt.AppContext appContext, java.awt.Container c, int x, int y, int w, int h)

        if (w > 0 && h > 0) {
            synchronized(this) {
                Rectangle dirty = hwDirtyComponents.get(c);
                if (dirty == null) {
                    hwDirtyComponents.put(c, new Rectangle(x, y, w, h));
                }
                else {
                    hwDirtyComponents.put(c, SwingUtilities.computeUnion(
                                              x, y, w, h, dirty));
                }
            }
            SystemEventQueueUtilities.queueComponentWorkRequest(c, appContext);
        }
    
voidnativeQueueSurfaceDataRunnable(sun.awt.AppContext appContext, java.awt.Component c, java.lang.Runnable r)

        synchronized(this) {
            if (runnableList == null) {
                runnableList = new LinkedList<Runnable>();
            }
            runnableList.add(r);
        }
        SystemEventQueueUtilities.queueComponentWorkRequest(c, appContext);
    
voidpaint(javax.swing.JComponent paintingComponent, javax.swing.JComponent bufferComponent, java.awt.Graphics g, int x, int y, int w, int h)
Paints a region of a component

param
paintingComponent Component to paint
param
bufferComponent Component to obtain buffer for
param
g Graphics to paint to
param
x X-coordinate
param
y Y-coordinate
param
w Width
param
h Height

        PaintManager paintManager = getPaintManager();
        if (!isPaintingThread()) {
            // We're painting to two threads at once.  PaintManager deals
            // with this a bit better than BufferStrategyPaintManager, use
            // it to avoid possible exceptions/corruption.
            if (paintManager.getClass() != PaintManager.class) {
                paintManager = new PaintManager();
                paintManager.repaintManager = this;
            }
        }
        if (!paintManager.paint(paintingComponent, bufferComponent, g,
                                x, y, w, h)) {
            g.setClip(x, y, w, h);
            paintingComponent.paintToOffscreen(g, x, y, w, h, x + w, y + h);
        }
    
public voidpaintDirtyRegions()
Paint all of the components that have been marked dirty.

see
#addDirtyRegion

	synchronized(this) {  // swap for thread safety
	    Map<Component,Rectangle> tmp = tmpDirtyComponents;
	    tmpDirtyComponents = dirtyComponents;
	    dirtyComponents = tmp;
	    dirtyComponents.clear();
	}
        paintDirtyRegions(tmpDirtyComponents);
    
private voidpaintDirtyRegions(java.util.Map tmpDirtyComponents)

        int i, count;
	java.util.List<Component> roots;
        Component dirtyComponent;

        count = tmpDirtyComponents.size();
        if (count == 0) {
            return;
        } 

        Rectangle rect;
        int localBoundsX = 0;
        int localBoundsY = 0;
        int localBoundsH = 0;
        int localBoundsW = 0;	
        Enumeration keys;

        roots = new ArrayList<Component>(count);

        for (Component dirty : tmpDirtyComponents.keySet()) {
            collectDirtyComponents(tmpDirtyComponents, dirty, roots);
        }

        count = roots.size();
        //        System.out.println("roots size is " + count);
        painting = true;
        try {
            for(i=0 ; i < count ; i++) {
                dirtyComponent = roots.get(i);
                rect = tmpDirtyComponents.get(dirtyComponent);
                //            System.out.println("Should refresh :" + rect);
                localBoundsH = dirtyComponent.getHeight();
                localBoundsW = dirtyComponent.getWidth();

                SwingUtilities.computeIntersection(localBoundsX, 
                                                   localBoundsY,
                                                   localBoundsW,
                                                   localBoundsH,
                                                   rect);
                if (dirtyComponent instanceof JComponent) {
                    ((JComponent)dirtyComponent).paintImmediately(
                        rect.x,rect.y,rect.width, rect.height);
                }
                else if (dirtyComponent.isShowing()) {
                    Graphics g = JComponent.safelyGetGraphics(
                            dirtyComponent, dirtyComponent);
                    // If the Graphics goes away, it means someone disposed of
                    // the window, don't do anything.
                    if (g != null) {
                        g.setClip(rect.x, rect.y, rect.width, rect.height);
                        try {
                            dirtyComponent.paint(g);
                        } finally {
                            g.dispose();
                        }
                    }
                }
                // If the repaintRoot has been set, service it now and
                // remove any components that are children of repaintRoot.
                if (repaintRoot != null) {
                    adjustRoots(repaintRoot, roots, i + 1);
                    count = roots.size();
                    paintManager.isRepaintingRoot = true;
                    repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
                                                 repaintRoot.getHeight());
                    paintManager.isRepaintingRoot = false;
                    // Only service repaintRoot once.
                    repaintRoot = null;
                }
            }
        } finally {
            painting = false;
        }
	tmpDirtyComponents.clear();
    
public synchronized voidremoveInvalidComponent(javax.swing.JComponent component)
Remove a component from the list of invalid components.

see
#addInvalidComponent

        if(invalidComponents != null) {
            int index = invalidComponents.indexOf(component);
            if(index != -1) {
                invalidComponents.remove(index);
            }
        }
    
voidresetDoubleBuffer()
This resets the double buffer. Actually, it marks the double buffer as invalid, the double buffer will then be recreated on the next invocation of getOffscreenBuffer.

	if (standardDoubleBuffer != null) {
	    standardDoubleBuffer.needsReset = true;
	}
    
voidresetVolatileDoubleBuffer(java.awt.GraphicsConfiguration gc)
This resets the volatile double buffer.

        Image image = volatileMap.remove(gc);
        if (image != null) {
            image.flush();
        }
    
voidscheduleHeavyWeightPaints()

        Map<Container,Rectangle> hws;

        synchronized(this) {
            if (hwDirtyComponents.size() == 0) {
                return;
            }
            hws = hwDirtyComponents;
            hwDirtyComponents =  new IdentityHashMap<Container,Rectangle>();
        }
        for (Container hw : hws.keySet()) {
            Rectangle dirty = hws.get(hw);
            if (hw instanceof Window) {
                addDirtyRegion((Window)hw, dirty.x, dirty.y,
                               dirty.width, dirty.height);
            }
            else if (hw instanceof Applet) {
                addDirtyRegion((Applet)hw, dirty.x, dirty.y,
                               dirty.width, dirty.height);
            }
            else { // SwingHeavyWeight
                addDirtyRegion0(hw, dirty.x, dirty.y,
                                dirty.width, dirty.height);
            }
        }
    
voidseqPaintDirtyRegions()
This is invoked from SystemEventQueueUtilities. It's needed for backward compatability in so far as RepaintManager would previously not see paint requests for top levels, so, we have to make sure a subclass correctly paints any dirty top levels.

        Map<Component,Rectangle> dirtyComponents;
        java.util.List<Runnable> runnableList;
        synchronized(this) {
            dirtyComponents = this.dirtyComponents;
            runnableList = this.runnableList;
            this.runnableList = null;
        }
        if (runnableList != null) {
            for (Runnable runnable : runnableList) {
                runnable.run();
            }
        }
        paintDirtyRegions();
        if (dirtyComponents.size() > 0) {
            // This'll only happen if a subclass isn't correctly dealing
            // with toplevels.
            paintDirtyRegions(dirtyComponents);
        }
    
public static voidsetCurrentManager(javax.swing.RepaintManager aRepaintManager)
Set the RepaintManager that should be used for the calling thread. aRepaintManager will become the current RepaintManager for the calling thread's thread group.

param
aRepaintManager the RepaintManager object to use

        if (aRepaintManager != null) {
            SwingUtilities.appContextPut(repaintManagerKey, aRepaintManager);
        } else {
            SwingUtilities.appContextRemove(repaintManagerKey);
        }
    
public voidsetDoubleBufferMaximumSize(java.awt.Dimension d)
Set the maximum double buffer size.

        doubleBufferMaxSize = d;
        if (doubleBufferMaxSize == null) {
            clearImages();
        } else {
            clearImages(d.width, d.height);
        }
    
public voidsetDoubleBufferingEnabled(boolean aFlag)
Enables or disables double buffering in this RepaintManager. CAUTION: The default value for this property is set for optimal paint performance on the given platform and it is not recommended that programs modify this property directly.

param
aFlag true to activate double buffering
see
#isDoubleBufferingEnabled

        doubleBufferingEnabled = aFlag;
        PaintManager paintManager = getPaintManager();
        if (!aFlag && paintManager.getClass() != PaintManager.class) {
            setPaintManager(new PaintManager());
        }
    
voidsetPaintManager(javax.swing.RepaintManager$PaintManager paintManager)
Sets the PaintManager that is used to handle all double buffered painting.

param
paintManager The PaintManager to use. Passing in null indicates the fallback PaintManager should be used.

        if (paintManager == null) {
            paintManager = new PaintManager();
        }
        PaintManager oldPaintManager;
        synchronized(this) {
            oldPaintManager = this.paintManager;
            this.paintManager = paintManager;
            paintManager.repaintManager = this;
        }
        if (oldPaintManager != null) {
            oldPaintManager.dispose();
        }
    
booleanshow(java.awt.Container c, int x, int y, int w, int h)
If possible this will show a previously rendered portion of a Component. If successful, this will return true, otherwise false.

WARNING: This method is invoked from the native toolkit thread, be very careful as to what methods this invokes!

        return getPaintManager().show(c, x, y, w, h);
    
public synchronized java.lang.StringtoString()
Returns a string that displays and identifies this object's properties.

return
a String representation of this object

	StringBuffer sb = new StringBuffer();
	if(dirtyComponents != null) 
	    sb.append("" + dirtyComponents);
        return sb.toString();
    
booleanuseVolatileDoubleBuffer()
Returns true if we should use the Image returned from getVolatileOffscreenBuffer to do double buffering.

        return volatileImageBufferEnabled;
    
public voidvalidateInvalidComponents()
Validate all of the components that have been marked invalid.

see
#addInvalidComponent

        java.util.List<Component> ic;
        synchronized(this) {
            if(invalidComponents == null) {
                return;
	    }
            ic = invalidComponents;
            invalidComponents = null;
        }
	int n = ic.size();
        for(int i = 0; i < n; i++) {
            ic.get(i).validate();
        }