KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > RepaintManager


1 /*
2  * @(#)RepaintManager.java 1.60 04/02/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing;
8
9
10 import java.awt.*;
11 import java.awt.event.*;
12 import java.awt.peer.ComponentPeer;
13 import java.awt.peer.ContainerPeer;
14 import java.awt.image.VolatileImage JavaDoc;
15 import java.util.*;
16 import java.applet.*;
17
18 import sun.security.action.GetPropertyAction;
19
20
21 /**
22  * This class manages repaint requests, allowing the number
23  * of repaints to be minimized, for example by collapsing multiple
24  * requests into a single repaint for members of a component tree.
25  *
26  * @version 1.60 02/18/04
27  * @author Arnaud Weber
28  */

29 public class RepaintManager
30 {
31     /**
32      * Maps from GraphicsConfiguration to VolatileImage.
33      */

34     private Map volatileMap = new HashMap(1);
35      
36     Hashtable dirtyComponents = new Hashtable();
37     Hashtable tmpDirtyComponents = new Hashtable();
38     Vector invalidComponents;
39
40     boolean doubleBufferingEnabled = true;
41
42     private Dimension doubleBufferMaxSize;
43
44     // Support for both the standard and volatile offscreen buffers exists to
45
// provide backwards compatibility for the [rare] programs which may be
46
// calling getOffScreenBuffer() and not expecting to get a VolatileImage.
47
// Swing internally is migrating to use *only* the volatile image buffer.
48

49     // Support for standard offscreen buffer
50
//
51
DoubleBufferInfo standardDoubleBuffer;
52
53     private static final Object JavaDoc repaintManagerKey = RepaintManager JavaDoc.class;
54
55     // Whether or not a VolatileImage should be used for double-buffered painting
56
static boolean volatileImageBufferEnabled = true;
57
58     // The maximum number of times Swing will attempt to use the VolatileImage
59
// buffer during a paint operation.
60
static final int VOLATILE_LOOP_MAX = 2;
61
62     static {
63     String JavaDoc vib = (String JavaDoc) java.security.AccessController.doPrivileged(
64                new GetPropertyAction("swing.volatileImageBufferEnabled"));
65     volatileImageBufferEnabled = (vib == null || vib.equals("true"));
66     }
67
68     /**
69      * Return the RepaintManager for the calling thread given a Component.
70      *
71      * @param c a Component -- unused in the default implementation, but could
72      * be used by an overridden version to return a different RepaintManager
73      * depending on the Component
74      * @return the RepaintManager object
75      */

76     public static RepaintManager JavaDoc currentManager(Component c) {
77         // Note: SystemEventQueueUtilities.ComponentWorkRequest passes
78
// in null as the component, so if component is ever used to
79
// determine the current RepaintManager, SystemEventQueueUtilities
80
// will need to be modified accordingly.
81
RepaintManager JavaDoc result = (RepaintManager JavaDoc) SwingUtilities.appContextGet(repaintManagerKey);
82         if(result == null) {
83             result = new RepaintManager JavaDoc();
84             SwingUtilities.appContextPut(repaintManagerKey, result);
85         }
86     return result;
87     }
88     
89     /**
90      * Return the RepaintManager for the calling thread given a JComponent.
91      * <p>
92     * Note: This method exists for backward binary compatibility with earlier
93      * versions of the Swing library. It simply returns the result returned by
94      * {@link #currentManager(Component)}.
95      *
96      * @param c a JComponent -- unused
97      * @return the RepaintManager object
98      */

99     public static RepaintManager JavaDoc currentManager(JComponent JavaDoc c) {
100     return currentManager((Component)c);
101     }
102
103
104     /**
105      * Set the RepaintManager that should be used for the calling
106      * thread. <b>aRepaintManager</b> will become the current RepaintManager
107      * for the calling thread's thread group.
108      * @param aRepaintManager the RepaintManager object to use
109      */

110     public static void setCurrentManager(RepaintManager JavaDoc aRepaintManager) {
111         if (aRepaintManager != null) {
112             SwingUtilities.appContextPut(repaintManagerKey, aRepaintManager);
113         } else {
114             SwingUtilities.appContextRemove(repaintManagerKey);
115         }
116     }
117
118     /**
119      * Create a new RepaintManager instance. You rarely call this constructor.
120      * directly. To get the default RepaintManager, use
121      * RepaintManager.currentManager(JComponent) (normally "this").
122      */

123     public RepaintManager() {
124     Object JavaDoc dbe = java.security.AccessController.doPrivileged(
125                new GetPropertyAction("awt.nativeDoubleBuffering"));
126         boolean nativeDoubleBuffering = (dbe != null) ?
127                       Boolean.valueOf(dbe.toString()).booleanValue() : false;
128         // If native doublebuffering is being used, do NOT use
129
// Swing doublebuffering.
130
doubleBufferingEnabled = !nativeDoubleBuffering;
131     }
132
133
134     /**
135      * Mark the component as in need of layout and queue a runnable
136      * for the event dispatching thread that will validate the components
137      * first isValidateRoot() ancestor.
138      *
139      * @see JComponent#isValidateRoot
140      * @see #removeInvalidComponent
141      */

142     public synchronized void addInvalidComponent(JComponent JavaDoc invalidComponent)
143     {
144         Component validateRoot = null;
145
146     /* Find the first JComponent ancestor of this component whose
147      * isValidateRoot() method returns true.
148      */

149         for(Component c = invalidComponent; c != null; c = c.getParent()) {
150         if ((c instanceof CellRendererPane JavaDoc) || (c.getPeer() == null)) {
151         return;
152         }
153         if ((c instanceof JComponent JavaDoc) && (((JComponent JavaDoc)c).isValidateRoot())) {
154         validateRoot = c;
155         break;
156         }
157     }
158         
159     /* There's no validateRoot to apply validate to, so we're done.
160      */

161     if (validateRoot == null) {
162         return;
163     }
164
165     /* If the validateRoot and all of its ancestors aren't visible
166      * then we don't do anything. While we're walking up the tree
167      * we find the root Window or Applet.
168      */

169     Component root = null;
170     
171     for(Component c = validateRoot; c != null; c = c.getParent()) {
172         if (!c.isVisible() || (c.getPeer() == null)) {
173         return;
174         }
175         if ((c instanceof Window) || (c instanceof Applet)) {
176         root = c;
177         break;
178         }
179     }
180
181     if (root == null) {
182         return;
183     }
184        
185     /* Lazily create the invalidateComponents vector and add the
186      * validateRoot if it's not there already. If this validateRoot
187      * is already in the vector, we're done.
188      */

189     if (invalidComponents == null) {
190         invalidComponents = new Vector();
191     }
192     else {
193         int n = invalidComponents.size();
194         for(int i = 0; i < n; i++) {
195         if(validateRoot == (Component)(invalidComponents.elementAt(i))) {
196             return;
197         }
198         }
199     }
200     invalidComponents.addElement(validateRoot);
201
202     /* Queues a Runnable that calls RepaintManager.validateInvalidComponents()
203      * and RepaintManager.paintDirtyRegions() with SwingUtilities.invokeLater().
204      */

205     SystemEventQueueUtilities.queueComponentWorkRequest(root);
206     }
207
208
209     /**
210      * Remove a component from the list of invalid components.
211      *
212      * @see #addInvalidComponent
213      */

214     public synchronized void removeInvalidComponent(JComponent JavaDoc component) {
215         if(invalidComponents != null) {
216             int index = invalidComponents.indexOf(component);
217             if(index != -1) {
218                 invalidComponents.removeElementAt(index);
219             }
220         }
221     }
222
223
224     /**
225      * Add a component in the list of components that should be refreshed.
226      * If <i>c</i> already has a dirty region, the rectangle <i>(x,y,w,h)</i>
227      * will be unioned with the region that should be redrawn.
228      *
229      * @see JComponent#repaint
230      */

231     public void addDirtyRegion(JComponent JavaDoc c, int x, int y, int w, int h)
232     {
233     /* Special cases we don't have to bother with.
234      */

235         if ((w <= 0) || (h <= 0) || (c == null)) {
236             return;
237         }
238
239     if ((c.getWidth() <= 0) || (c.getHeight() <= 0)) {
240         return;
241     }
242
243         if (extendDirtyRegion(c, x, y, w, h)) {
244             // Component was already marked as dirty, region has been
245
// extended, no need to continue.
246
return;
247         }
248
249     /* Make sure that c and all it ancestors (up to an Applet or
250      * Window) are visible. This loop has the same effect as
251      * checking c.isShowing() (and note that it's still possible
252      * that c is completely obscured by an opaque ancestor in
253      * the specified rectangle).
254      */

255     Component root = null;
256
257         // Note: We can't synchronize around this, Frame.getExtendedState
258
// is synchronized so that if we were to synchronize around this
259
// it could lead to the possibility of getting locks out
260
// of order and deadlocking.
261
for (Container p = c; p != null; p = p.getParent()) {
262         if (!p.isVisible() || (p.getPeer() == null)) {
263         return;
264         }
265         if ((p instanceof Window) || (p instanceof Applet)) {
266                 // Iconified frames are still visible!
267
if (p instanceof Frame &&
268                         (((Frame)p).getExtendedState() & Frame.ICONIFIED) ==
269                                     Frame.ICONIFIED) {
270                     return;
271                 }
272         root = p;
273         break;
274         }
275     }
276
277     if (root == null) return;
278
279         synchronized(this) {
280             if (extendDirtyRegion(c, x, y, w, h)) {
281                 // In between last check and this check another thread
282
// queued up runnable, can bail here.
283
return;
284             }
285             dirtyComponents.put(c, new Rectangle(x, y, w, h));
286         }
287
288     /* Queues a Runnable that calls validateInvalidComponents() and
289      * rm.paintDirtyRegions() with SwingUtilities.invokeLater().
290      */

291     SystemEventQueueUtilities.queueComponentWorkRequest(root);
292     }
293
294     /**
295      * Extends the dirty region for the specified component to include
296      * the new region.
297      *
298      * @return false if <code>c</code> is not yet marked dirty.
299      */

300     private synchronized boolean extendDirtyRegion(
301         Component c, int x, int y, int w, int h) {
302         Rectangle r = (Rectangle)dirtyComponents.get(c);
303         if (r != null) {
304             // A non-null r implies c is already marked as dirty,
305
// and that the parent is valid. Therefore we can
306
// just union the rect and bail.
307
SwingUtilities.computeUnion(x, y, w, h, r);
308             return true;
309         }
310         return false;
311     }
312
313     /** Return the current dirty region for a component.
314      * Return an empty rectangle if the component is not
315      * dirty.
316      */

317     public Rectangle getDirtyRegion(JComponent JavaDoc aComponent) {
318     Rectangle r = null;
319     synchronized(this) {
320         r = (Rectangle)dirtyComponents.get(aComponent);
321     }
322     if(r == null)
323         return new Rectangle(0,0,0,0);
324     else
325         return new Rectangle(r);
326     }
327
328     /**
329      * Mark a component completely dirty. <b>aComponent</b> will be
330      * completely painted during the next paintDirtyRegions() call.
331      */

332     public void markCompletelyDirty(JComponent JavaDoc aComponent) {
333     addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE);
334     }
335         
336     /**
337      * Mark a component completely clean. <b>aComponent</b> will not
338      * get painted during the next paintDirtyRegions() call.
339      */

340     public void markCompletelyClean(JComponent JavaDoc aComponent) {
341     synchronized(this) {
342         dirtyComponents.remove(aComponent);
343     }
344     }
345
346     /**
347      * Convenience method that returns true if <b>aComponent</b> will be completely
348      * painted during the next paintDirtyRegions(). If computing dirty regions is
349      * expensive for your component, use this method and avoid computing dirty region
350      * if it return true.
351      */

352     public boolean isCompletelyDirty(JComponent JavaDoc aComponent) {
353     Rectangle r;
354     
355     r = getDirtyRegion(aComponent);
356     if(r.width == Integer.MAX_VALUE &&
357        r.height == Integer.MAX_VALUE)
358         return true;
359     else
360         return false;
361     }
362
363
364     /**
365      * Validate all of the components that have been marked invalid.
366      * @see #addInvalidComponent
367      */

368     public void validateInvalidComponents() {
369         Vector ic;
370         synchronized(this) {
371             if(invalidComponents == null) {
372                 return;
373         }
374             ic = invalidComponents;
375             invalidComponents = null;
376         }
377     int n = ic.size();
378         for(int i = 0; i < n; i++) {
379             ((Component)ic.elementAt(i)).validate();
380         }
381     }
382     
383
384     /**
385      * Paint all of the components that have been marked dirty.
386      *
387      * @see #addDirtyRegion
388      */

389     public void paintDirtyRegions() {
390         int i, count;
391     Vector roots;
392         JComponent JavaDoc dirtyComponent;
393
394     synchronized(this) { // swap for thread safety
395
Hashtable tmp = tmpDirtyComponents;
396         tmpDirtyComponents = dirtyComponents;
397         dirtyComponents = tmp;
398         dirtyComponents.clear();
399     }
400
401         count = tmpDirtyComponents.size();
402         if (count == 0) {
403             return;
404         }
405
406         Rectangle rect;
407         int localBoundsX = 0;
408         int localBoundsY = 0;
409         int localBoundsH = 0;
410         int localBoundsW = 0;
411         Enumeration keys;
412
413         roots = new Vector(count);
414         keys = tmpDirtyComponents.keys();
415
416         while(keys.hasMoreElements()) {
417             dirtyComponent = (JComponent JavaDoc) keys.nextElement();
418             collectDirtyComponents(tmpDirtyComponents, dirtyComponent, roots);
419         }
420
421         count = roots.size();
422         // System.out.println("roots size is " + count);
423
for(i=0 ; i < count ; i++) {
424             dirtyComponent = (JComponent JavaDoc) roots.elementAt(i);
425             rect = (Rectangle) tmpDirtyComponents.get(dirtyComponent);
426             // System.out.println("Should refresh :" + rect);
427
localBoundsH = dirtyComponent.getHeight();
428             localBoundsW = dirtyComponent.getWidth();
429
430             SwingUtilities.computeIntersection(localBoundsX,
431                            localBoundsY,
432                            localBoundsW,
433                            localBoundsH,
434                            rect);
435             // System.out.println("** paint of " + dirtyComponent + rect);
436
if (rect.x == 0 && rect.y == 0 &&
437                          rect.width == dirtyComponent.getWidth() &&
438                          rect.height == dirtyComponent.getHeight()) {
439                 Container parent = dirtyComponent.getParent();
440                 ComponentPeer parentPeer;
441                 if (parent != null && !parent.isLightweight() &&
442                     (parentPeer = parent.getPeer()) != null) {
443                     // Cancel any pending paints on the heavy weight peer.
444
// This avoid duplicate painting.
445
((ContainerPeer)parentPeer).cancelPendingPaint(
446                                     dirtyComponent.getX(),
447                                     dirtyComponent.getY(),
448                                     rect.width, rect.height);
449                 }
450             }
451             dirtyComponent.paintImmediately(rect.x,rect.y,rect.width,rect.height);
452         }
453     tmpDirtyComponents.clear();
454     }
455
456
457     Rectangle tmp = new Rectangle();
458
459     void collectDirtyComponents(Hashtable dirtyComponents,
460                 JComponent JavaDoc dirtyComponent,
461                 Vector roots) {
462         int dx, dy, rootDx, rootDy;
463         Component component, rootDirtyComponent,parent;
464     //Rectangle tmp;
465
Rectangle cBounds;
466
467         // Find the highest parent which is dirty. When we get out of this
468
// rootDx and rootDy will contain the translation from the
469
// rootDirtyComponent's coordinate system to the coordinates of the
470
// original dirty component. The tmp Rect is also used to compute the
471
// visible portion of the dirtyRect.
472

473         component = rootDirtyComponent = dirtyComponent;
474
475         int x = dirtyComponent.getX();
476         int y = dirtyComponent.getY();
477         int w = dirtyComponent.getWidth();
478         int h = dirtyComponent.getHeight();
479
480         dx = rootDx = 0;
481         dy = rootDy = 0;
482         tmp.setBounds((Rectangle) dirtyComponents.get(dirtyComponent));
483
484         // System.out.println("Collect dirty component for bound " + tmp +
485
// "component bounds is " + cBounds);;
486
SwingUtilities.computeIntersection(0,0,w,h,tmp);
487
488         if (tmp.isEmpty()) {
489             // System.out.println("Empty 1");
490
return;
491         }
492
493         for(;;) {
494             parent = component.getParent();
495             if(parent == null)
496                 break;
497
498             if(!(parent instanceof JComponent JavaDoc))
499                 break;
500
501             component = parent;
502
503             dx += x;
504             dy += y;
505             tmp.setLocation(tmp.x + x, tmp.y + y);
506
507             x = component.getX();
508             y = component.getY();
509             w = component.getWidth();
510             h = component.getHeight();
511             tmp = SwingUtilities.computeIntersection(0,0,w,h,tmp);
512
513             if (tmp.isEmpty()) {
514                 // System.out.println("Empty 2");
515
return;
516             }
517
518             if (dirtyComponents.get(component) != null) {
519                 rootDirtyComponent = component;
520                 rootDx = dx;
521                 rootDy = dy;
522             }
523         }
524
525         if (dirtyComponent != rootDirtyComponent) {
526         Rectangle r;
527             tmp.setLocation(tmp.x + rootDx - dx,
528                 tmp.y + rootDy - dy);
529         r = (Rectangle)dirtyComponents.get(rootDirtyComponent);
530         SwingUtilities.computeUnion(tmp.x,tmp.y,tmp.width,tmp.height,r);
531         }
532
533         // If we haven't seen this root before, then we need to add it to the
534
// list of root dirty Views.
535

536         if (!roots.contains(rootDirtyComponent))
537             roots.addElement(rootDirtyComponent);
538     }
539
540
541     /**
542      * Returns a string that displays and identifies this
543      * object's properties.
544      *
545      * @return a String representation of this object
546      */

547     public synchronized String JavaDoc toString() {
548     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
549     if(dirtyComponents != null)
550         sb.append("" + dirtyComponents);
551         return sb.toString();
552     }
553
554
555    /**
556      * Return the offscreen buffer that should be used as a double buffer with
557      * the component <code>c</code>.
558      * By default there is a double buffer per RepaintManager.
559      * The buffer might be smaller than <code>(proposedWidth,proposedHeight)</code>
560      * This happens when the maximum double buffer size as been set for the receiving
561      * repaint manager.
562      */

563     public Image JavaDoc getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) {
564     return _getOffscreenBuffer(c, proposedWidth, proposedHeight);
565     }
566
567   /**
568    * Return a volatile offscreen buffer that should be used as a
569    * double buffer with the specified component <code>c</code>.
570    * The image returned will be an instance of VolatileImage, or null
571    * if a VolatileImage object could not be instantiated.
572    * This buffer might be smaller than <code>(proposedWidth,proposedHeight)</code>.
573    * This happens when the maximum double buffer size has been set for this
574    * repaint manager.
575    *
576    * @see java.awt.image.VolatileImage
577    * @since 1.4
578    */

579     public Image JavaDoc getVolatileOffscreenBuffer(Component c,
580                         int proposedWidth,int proposedHeight) {
581         GraphicsConfiguration config = c.getGraphicsConfiguration();
582         if (config == null) {
583             config = GraphicsEnvironment.getLocalGraphicsEnvironment().
584                             getDefaultScreenDevice().getDefaultConfiguration();
585         }
586     Dimension maxSize = getDoubleBufferMaximumSize();
587     int width = proposedWidth < 1 ? 1 :
588             (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
589         int height = proposedHeight < 1 ? 1 :
590             (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
591         VolatileImage JavaDoc image = (VolatileImage JavaDoc)volatileMap.get(config);
592         if (image == null || image.getWidth() < width ||
593                              image.getHeight() < height) {
594             if (image != null) {
595                 image.flush();
596             }
597             image = config.createCompatibleVolatileImage(width, height);
598             volatileMap.put(config, image);
599         }
600     return image;
601     }
602
603     private Image JavaDoc _getOffscreenBuffer(Component c, int proposedWidth, int proposedHeight) {
604     Dimension maxSize = getDoubleBufferMaximumSize();
605     DoubleBufferInfo doubleBuffer = null;
606         int width, height;
607
608         if (standardDoubleBuffer == null) {
609             standardDoubleBuffer = new DoubleBufferInfo();
610         }
611         doubleBuffer = standardDoubleBuffer;
612         
613     width = proposedWidth < 1? 1 :
614               (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
615         height = proposedHeight < 1? 1 :
616                   (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
617
618         if (doubleBuffer.needsReset || (doubleBuffer.image != null &&
619                                         (doubleBuffer.size.width < width ||
620                                          doubleBuffer.size.height < height))) {
621             doubleBuffer.needsReset = false;
622             if (doubleBuffer.image != null) {
623                 doubleBuffer.image.flush();
624                 doubleBuffer.image = null;
625             }
626             width = Math.max(doubleBuffer.size.width, width);
627             height = Math.max(doubleBuffer.size.height, height);
628         }
629
630     Image JavaDoc result = doubleBuffer.image;
631
632     if (doubleBuffer.image == null) {
633             result = c.createImage(width , height);
634             doubleBuffer.size = new Dimension(width, height);
635         if (c instanceof JComponent JavaDoc) {
636         ((JComponent JavaDoc)c).setCreatedDoubleBuffer(true);
637         doubleBuffer.image = result;
638         }
639         // JComponent will inform us when it is no longer valid
640
// (via removeNotify) we have no such hook to other components,
641
// therefore we don't keep a ref to the Component
642
// (indirectly through the Image) by stashing the image.
643
}
644         return result;
645     }
646
647
648     /** Set the maximum double buffer size. **/
649     public void setDoubleBufferMaximumSize(Dimension d) {
650         doubleBufferMaxSize = d;
651         if (standardDoubleBuffer != null && standardDoubleBuffer.image != null) {
652             if (standardDoubleBuffer.image.getWidth(null) > d.width ||
653         standardDoubleBuffer.image.getHeight(null) > d.height) {
654         standardDoubleBuffer.image = null;
655         }
656         }
657         // Clear out the VolatileImages
658
Iterator gcs = volatileMap.keySet().iterator();
659         while (gcs.hasNext()) {
660             GraphicsConfiguration gc = (GraphicsConfiguration)gcs.next();
661             VolatileImage JavaDoc image = (VolatileImage JavaDoc)volatileMap.get(gc);
662             if (image.getWidth() > d.width || image.getHeight() > d.height) {
663                 image.flush();
664                 gcs.remove();
665         }
666     }
667     }
668
669     /**
670      * Returns the maximum double buffer size.
671      *
672      * @return a Dimension object representing the maximum size
673      */

674     public Dimension getDoubleBufferMaximumSize() {
675     if (doubleBufferMaxSize == null) {
676         try {
677             doubleBufferMaxSize = Toolkit.getDefaultToolkit().getScreenSize();
678         } catch (HeadlessException e) {
679         doubleBufferMaxSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
680         }
681     }
682         return doubleBufferMaxSize;
683     }
684
685     /**
686      * Enables or disables double buffering in this RepaintManager.
687      * CAUTION: The default value for this property is set for optimal
688      * paint performance on the given platform and it is not recommended
689      * that programs modify this property directly.
690      *
691      * @param aFlag true to activate double buffering
692      * @see #isDoubleBufferingEnabled
693      */

694     public void setDoubleBufferingEnabled(boolean aFlag) {
695         doubleBufferingEnabled = aFlag;
696     }
697
698     /**
699      * Returns true if this RepaintManager is double buffered.
700      * The default value for this property may vary from platform
701      * to platform. On platforms where native double buffering
702      * is supported in the AWT, the default value will be <code>false</code>
703      * to avoid unnecessary buffering in Swing.
704      * On platforms where native double buffering is not supported,
705      * the default value will be <code>true</code>.
706      *
707      * @return true if this object is double buffered
708      */

709     public boolean isDoubleBufferingEnabled() {
710         return doubleBufferingEnabled;
711     }
712
713     /**
714      * This resets the double buffer. Actually, it marks the double buffer
715      * as invalid, the double buffer will then be recreated on the next
716      * invocation of getOffscreenBuffer.
717      */

718     void resetDoubleBuffer() {
719     if (standardDoubleBuffer != null) {
720         standardDoubleBuffer.needsReset = true;
721     }
722     }
723
724     /**
725      * This resets the volatile double buffer.
726      */

727     void resetVolatileDoubleBuffer(GraphicsConfiguration gc) {
728         Image JavaDoc image = (Image JavaDoc)volatileMap.remove(gc);
729         if (image != null) {
730             image.flush();
731         }
732     }
733
734     /**
735      * Returns true if we should use the <code>Image</code> returned
736      * from <code>getVolatileOffscreenBuffer</code> to do double buffering.
737      */

738     boolean useVolatileDoubleBuffer() {
739         return volatileImageBufferEnabled;
740     }
741
742     private class DoubleBufferInfo {
743         public Image JavaDoc image;
744         public Dimension size;
745         public boolean needsReset = false;
746     }
747 }
748
Popular Tags