/* RepaintManager.java --
   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.image.VolatileImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

/**
 * <p>The repaint manager holds a set of dirty regions, invalid components,
 * and a double buffer surface.  The dirty regions and invalid components
 * are used to coalesce multiple revalidate() and repaint() calls in the
 * component tree into larger groups to be refreshed "all at once"; the
 * double buffer surface is used by root components to paint
 * themselves.</p>
 *
 * <p>See <a
 * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">this
 * document</a> for more details.</p>
 *
 * @author Roman Kennke (kennke@aicas.com)
 * @author Graydon Hoare (graydon@redhat.com)
 * @author Audrius Meskauskas (audriusa@bioinformatics.org)
 */
public class RepaintManager
{
  /**
   * The current repaint managers, indexed by their ThreadGroups.
   */
  static WeakHashMap currentRepaintManagers;

  /**
   * A rectangle object to be reused in damaged regions calculation.
   */
  private static Rectangle rectCache = new Rectangle();

  /**
   * <p>A helper class which is placed into the system event queue at
   * various times in order to facilitate repainting and layout. There is
   * typically only one of these objects active at any time. When the
   * {@link RepaintManager} is told to queue a repaint, it checks to see if
   * a {@link RepaintWorker} is "live" in the system event queue, and if
   * not it inserts one using {@link SwingUtilities#invokeLater}.</p>
   *
   * <p>When the {@link RepaintWorker} comes to the head of the system
   * event queue, its {@link RepaintWorker#run} method is executed by the
   * swing paint thread, which revalidates all invalid components and
   * repaints any damage in the swing scene.</p>
   */
  private class RepaintWorker
    implements Runnable
  {

    boolean live;

    public RepaintWorker()
    {
      live = false;
    }

    public synchronized void setLive(boolean b) 
    {
      live = b;
    }

    public synchronized boolean isLive()
    {
      return live;
    }

    public void run()
    {
      try
        {
          ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
          RepaintManager rm =
            (RepaintManager) currentRepaintManagers.get(threadGroup);
          rm.validateInvalidComponents();
          rm.paintDirtyRegions();
        }
      finally
        {
          setLive(false);
        }
    }

  }

  /** 
   * A table storing the dirty regions of components.  The keys of this
   * table are components, the values are rectangles. Each component maps
   * to exactly one rectangle.  When more regions are marked as dirty on a
   * component, they are union'ed with the existing rectangle.
   *
   * This is package private to avoid a synthetic accessor method in inner
   * class.
   *
   * @see #addDirtyRegion
   * @see #getDirtyRegion
   * @see #isCompletelyDirty
   * @see #markCompletelyClean
   * @see #markCompletelyDirty
   */
  private HashMap dirtyComponents;

  /**
   * The dirtyComponents which is used in paintDiryRegions to avoid unnecessary
   * locking.
   */
  private HashMap dirtyComponentsWork;

  /**
   * A single, shared instance of the helper class. Any methods which mark
   * components as invalid or dirty eventually activate this instance. It
   * is added to the event queue if it is not already active, otherwise
   * reused.
   *
   * @see #addDirtyRegion
   * @see #addInvalidComponent
   */
  private RepaintWorker repaintWorker;

  /** 
   * The set of components which need revalidation, in the "layout" sense.
   * There is no additional information about "what kind of layout" they
   * need (as there is with dirty regions), so it is just a vector rather
   * than a table.
   *
   * @see #addInvalidComponent
   * @see #removeInvalidComponent
   * @see #validateInvalidComponents
   */
  private ArrayList invalidComponents;

  /** 
   * Whether or not double buffering is enabled on this repaint
   * manager. This is merely a hint to clients; the RepaintManager will
   * always return an offscreen buffer when one is requested.
   * 
   * @see #isDoubleBufferingEnabled
   * @see #setDoubleBufferingEnabled
   */
  private boolean doubleBufferingEnabled;

  /**
   * The offscreen buffers. This map holds one offscreen buffer per
   * Window/Applet and releases them as soon as the Window/Applet gets garbage
   * collected.
   */
  private WeakHashMap offscreenBuffers;

  /**
   * Indicates if the RepaintManager is currently repainting an area.
   */
  private boolean repaintUnderway;

  /**
   * This holds buffer commit requests when the RepaintManager is working.
   * This maps Component objects (the top level components) to Rectangle
   * objects (the area of the corresponding buffer that must be blitted on
   * the component).
   */
  private HashMap commitRequests;

  /**
   * The maximum width and height to allocate as a double buffer. Requests
   * beyond this size are ignored.
   *
   * @see #paintDirtyRegions
   * @see #getDoubleBufferMaximumSize
   * @see #setDoubleBufferMaximumSize
   */
  private Dimension doubleBufferMaximumSize;


  /**
   * Create a new RepaintManager object.
   */
  public RepaintManager()
  {
    dirtyComponents = new HashMap();
    dirtyComponentsWork = new HashMap();
    invalidComponents = new ArrayList();
    repaintWorker = new RepaintWorker();
    doubleBufferMaximumSize = new Dimension(2000,2000);
    doubleBufferingEnabled = true;
    offscreenBuffers = new WeakHashMap();
    repaintUnderway = false;
    commitRequests = new HashMap();
  }

  /**
   * Returns the <code>RepaintManager</code> for the current thread's
   * thread group. The default implementation ignores the
   * <code>component</code> parameter and returns the same repaint manager
   * for all components.
   *
   * @param component a component to look up the manager of
   *
   * @return the current repaint manager for the calling thread's thread group
   *         and the specified component
   *
   * @see #setCurrentManager
   */
  public static RepaintManager currentManager(Component component)
  {
    if (currentRepaintManagers == null)
      currentRepaintManagers = new WeakHashMap();
    ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
    RepaintManager currentManager =
      (RepaintManager) currentRepaintManagers.get(threadGroup);
    if (currentManager == null)
      {
        currentManager = new RepaintManager();
        currentRepaintManagers.put(threadGroup, currentManager);
      }
    return currentManager;
  }

  /**
   * Returns the <code>RepaintManager</code> for the current thread's
   * thread group. The default implementation ignores the
   * <code>component</code> parameter and returns the same repaint manager
   * for all components.
   *
   * This method is only here for backwards compatibility with older versions
   * of Swing and simply forwards to {@link #currentManager(Component)}.
   *
   * @param component a component to look up the manager of
   *
   * @return the current repaint manager for the calling thread's thread group
   *         and the specified component
   *
   * @see #setCurrentManager
   */
  public static RepaintManager currentManager(JComponent component)
  {
    return currentManager((Component)component);
  }

  /**
   * Sets the repaint manager for the calling thread's thread group.
   *
   * @param manager the repaint manager to set for the current thread's thread
   *        group
   *
   * @see #currentManager(Component)
   */
  public static void setCurrentManager(RepaintManager manager)
  {
    if (currentRepaintManagers == null)
      currentRepaintManagers = new WeakHashMap();

    ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
    currentRepaintManagers.put(threadGroup, manager);
  }

  /**
   * Add a component to the {@link #invalidComponents} vector. If the
   * {@link #repaintWorker} class is not active, insert it in the system
   * event queue.
   *
   * @param component The component to add
   *
   * @see #removeInvalidComponent
   */
  public void addInvalidComponent(JComponent component)
  {
    Component validateRoot = null;
    Component c = component;
    while (c != null)
      {
        // Special cases we don't bother validating are when the invalidated
        // component (or any of it's ancestors) is inside a CellRendererPane
        // or if it doesn't have a peer yet (== not displayable).
        if (c instanceof CellRendererPane || ! c.isDisplayable())
          return;
        if (c instanceof JComponent && ((JComponent) c).isValidateRoot())
          {
            validateRoot = c;
            break;
          }

        c = c.getParent();
      }

    // If we didn't find a validate root, then we don't validate.
    if (validateRoot == null)
      return;

    // Make sure the validate root and all of it's ancestors are visible.
    c = validateRoot;
    while (c != null)
      {
        if (! c.isVisible() || ! c.isDisplayable())
          return;
        c = c.getParent();
      }

    if (invalidComponents.contains(validateRoot))
      return;

    //synchronized (invalidComponents)
    //  {
        invalidComponents.add(validateRoot);
    //  }

    if (! repaintWorker.isLive())
      {
        repaintWorker.setLive(true);
        SwingUtilities.invokeLater(repaintWorker);
      }
  }

  /**
   * Remove a component from the {@link #invalidComponents} vector.
   *
   * @param component The component to remove
   *
   * @see #addInvalidComponent
   */
  public void removeInvalidComponent(JComponent component)
  {
    synchronized (invalidComponents)
      {
        invalidComponents.remove(component);
      }
  }

  /**
   * Add a region to the set of dirty regions for a specified component.
   * This involves union'ing the new region with any existing dirty region
   * associated with the component. If the {@link #repaintWorker} class
   * is not active, insert it in the system event queue.
   *
   * @param component The component to add a dirty region for
   * @param x The left x coordinate of the new dirty region
   * @param y The top y coordinate of the new dirty region
   * @param w The width of the new dirty region
   * @param h The height of the new dirty region
   *
   * @see #addDirtyRegion
   * @see #getDirtyRegion
   * @see #isCompletelyDirty
   * @see #markCompletelyClean
   * @see #markCompletelyDirty
   */
  public void addDirtyRegion(JComponent component, int x, int y,
                             int w, int h)
  {
    if (w <= 0 || h <= 0 || !component.isShowing())
      return;

    Component parent = component.getParent();
    
    component.computeVisibleRect(rectCache);
    SwingUtilities.computeIntersection(x, y, w, h, rectCache);

    if (! rectCache.isEmpty())
      {
        if (dirtyComponents.containsKey(component))
          {
            SwingUtilities.computeUnion(rectCache.x, rectCache.y,
                                        rectCache.width, rectCache.height,
                                   (Rectangle) dirtyComponents.get(component));
          }
        else
          {
            synchronized (dirtyComponents)
              {
                dirtyComponents.put(component, rectCache.getBounds());
              }
          }

        if (! repaintWorker.isLive())
          {
            repaintWorker.setLive(true);
            SwingUtilities.invokeLater(repaintWorker);
          }
      }
  }

  /**
   * Get the dirty region associated with a component, or <code>null</code>
   * if the component has no dirty region.
   *
   * @param component The component to get the dirty region of
   *
   * @return The dirty region of the component
   *
   * @see #dirtyComponents
   * @see #addDirtyRegion
   * @see #isCompletelyDirty
   * @see #markCompletelyClean
   * @see #markCompletelyDirty
   */
  public Rectangle getDirtyRegion(JComponent component)
  {
    Rectangle dirty = (Rectangle) dirtyComponents.get(component);
    if (dirty == null)
      dirty = new Rectangle();
    return dirty;
  }
  
  /**
   * Mark a component as dirty over its entire bounds.
   *
   * @param component The component to mark as dirty
   *
   * @see #dirtyComponents
   * @see #addDirtyRegion
   * @see #getDirtyRegion
   * @see #isCompletelyDirty
   * @see #markCompletelyClean
   */
  public void markCompletelyDirty(JComponent component)
  {
    addDirtyRegion(component, 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
  }

  /**
   * Remove all dirty regions for a specified component
   *
   * @param component The component to mark as clean
   *
   * @see #dirtyComponents
   * @see #addDirtyRegion
   * @see #getDirtyRegion
   * @see #isCompletelyDirty
   * @see #markCompletelyDirty
   */
  public void markCompletelyClean(JComponent component)
  {
    synchronized (dirtyComponents)
      {
        dirtyComponents.remove(component);
      }
  }

  /**
   * Return <code>true</code> if the specified component is completely
   * contained within its dirty region, otherwise <code>false</code>
   *
   * @param component The component to check for complete dirtyness
   *
   * @return Whether the component is completely dirty
   *
   * @see #dirtyComponents
   * @see #addDirtyRegion
   * @see #getDirtyRegion
   * @see #isCompletelyDirty
   * @see #markCompletelyClean
   */
  public boolean isCompletelyDirty(JComponent component)
  {
    boolean dirty = false;
    Rectangle r = getDirtyRegion(component);
    if(r.width == Integer.MAX_VALUE && r.height == Integer.MAX_VALUE)
      dirty = true;
    return dirty;
  }

  /**
   * Validate all components which have been marked invalid in the {@link
   * #invalidComponents} vector.
   */
  public void validateInvalidComponents()
  {
    // We don't use an iterator here because that would fail when there are
    // components invalidated during the validation of others, which happens
    // quite frequently. Instead we synchronize the access a little more.
    while (invalidComponents.size() > 0)
      {
        Component comp;
        synchronized (invalidComponents)
          {
            comp = (Component) invalidComponents.remove(0);
          }
        // Validate the validate component.
        if (! (comp.isVisible() && comp.isShowing()))
          continue;
        comp.validate();
      }
  }

  /**
   * Repaint all regions of all components which have been marked dirty in the
   * {@link #dirtyComponents} table.
   */
  public void paintDirtyRegions()
  {
    // Short cicuit if there is nothing to paint.
    if (dirtyComponents.size() == 0)
      return;

    // Swap dirtyRegions with dirtyRegionsWork to avoid locking.
    synchronized (dirtyComponents)
      {
        HashMap swap = dirtyComponents;
        dirtyComponents = dirtyComponentsWork;
        dirtyComponentsWork = swap;
      }

    // Compile a set of repaint roots.
    HashSet repaintRoots = new HashSet();
    Set components = dirtyComponentsWork.keySet();
    for (Iterator i = components.iterator(); i.hasNext();)
      {
        JComponent dirty = (JComponent) i.next();
        compileRepaintRoots(dirtyComponentsWork, dirty, repaintRoots);
      }

    repaintUnderway = true;
    for (Iterator i = repaintRoots.iterator(); i.hasNext();)
      {
        JComponent comp = (JComponent) i.next();
        Rectangle damaged = (Rectangle) dirtyComponentsWork.remove(comp);
        if (damaged == null || damaged.isEmpty())
          continue;
        comp.paintImmediately(damaged);
      }
    dirtyComponentsWork.clear();
    repaintUnderway = false;
    commitRemainingBuffers();
  }
  
  /**
   * Compiles a list of components that really get repainted. This is called
   * once for each component in the dirtyComponents HashMap, each time with
   * another <code>dirty</code> parameter. This searches up the component
   * hierarchy of <code>dirty</code> to find the highest parent that is also
   * marked dirty and merges the dirty regions.
   *
   * @param dirtyRegions the dirty regions 
   * @param dirty the component for which to find the repaint root
   * @param roots the list to which new repaint roots get appended
   */
  private void compileRepaintRoots(HashMap dirtyRegions, JComponent dirty,
                                   HashSet roots)
  {
    Component current = dirty;
    Component root = dirty;

    // Search the highest component that is also marked dirty.
    Component parent;
    while (true)
      {
        parent = current.getParent();
        if (parent == null || !(parent instanceof JComponent))
          break;

        current = parent;
        // We can skip to the next up when this parent is not dirty.
        if (dirtyRegions.containsKey(parent))
          {
            root = current;
          }
      }

    // Merge the rectangles of the root and the requested component if
    // the are different.
    if (root != dirty)
      {
        Rectangle dirtyRect = (Rectangle) dirtyRegions.get(dirty);
        dirtyRect = SwingUtilities.convertRectangle(dirty, dirtyRect, root);
        Rectangle rootRect = (Rectangle) dirtyRegions.get(root);
        SwingUtilities.computeUnion(dirtyRect.x, dirtyRect.y, dirtyRect.width,
                                    dirtyRect.height, rootRect);
      }

    // Adds the root to the roots set.
    roots.add(root);
  }

  /**
   * Get an offscreen buffer for painting a component's image. This image
   * may be smaller than the proposed dimensions, depending on the value of
   * the {@link #doubleBufferMaximumSize} property.
   *
   * @param component The component to return an offscreen buffer for
   * @param proposedWidth The proposed width of the offscreen buffer
   * @param proposedHeight The proposed height of the offscreen buffer
   *
   * @return A shared offscreen buffer for painting
   */
  public Image getOffscreenBuffer(Component component, int proposedWidth,
                                  int proposedHeight)
  {
    Component root = SwingUtilities.getWindowAncestor(component);
    Image buffer = (Image) offscreenBuffers.get(root);
    if (buffer == null 
        || buffer.getWidth(null) < proposedWidth 
        || buffer.getHeight(null) < proposedHeight)
      {
        int width = Math.max(proposedWidth, root.getWidth());
        width = Math.min(doubleBufferMaximumSize.width, width);
        int height = Math.max(proposedHeight, root.getHeight());
        height = Math.min(doubleBufferMaximumSize.height, height);
        buffer = root.createImage(width, height);
        offscreenBuffers.put(root, buffer);
      }
    return buffer;
  }

  /**
   * Blits the back buffer of the specified root component to the screen. If
   * the RepaintManager is currently working on a paint request, the commit
   * requests are queued up and committed at once when the paint request is
   * done (by {@link #commitRemainingBuffers}). This is package private because
   * it must get called by JComponent.
   *
   * @param comp the component to be painted
   * @param area the area to paint on screen, in comp coordinates
   */
  void commitBuffer(Component comp, Rectangle area)
  {
    // Determine the component that we finally paint the buffer upon.
    // We need to paint on the nearest heavyweight component, so that Swing
    // hierarchies inside (non-window) heavyweights get painted correctly.
    // Otherwise we would end up blitting the backbuffer behind the heavyweight
    // which is wrong.
    Component root = getHeavyweightParent(comp);
    // FIXME: Optimize this.
    Rectangle rootRect = SwingUtilities.convertRectangle(comp, area, root);

    // We synchronize on dirtyComponents here because that is what
    // paintDirtyRegions also synchronizes on while painting.
    synchronized (dirtyComponents)
      {
        // If the RepaintManager is not currently painting, then directly
        // blit the requested buffer on the screen.
        if (true || ! repaintUnderway)
          {
            blitBuffer(root, rootRect);
          }

        // Otherwise queue this request up, until all the RepaintManager work
        // is done.
        else
          {
            if (commitRequests.containsKey(root))
              SwingUtilities.computeUnion(rootRect.x, rootRect.y,
                                          rootRect.width, rootRect.height,
                                         (Rectangle) commitRequests.get(root));
            else
              commitRequests.put(root, rootRect);
          }
      }
  }

  /**
   * Copies the buffer to the screen. Note that the root component here is
   * not necessarily the component with which the offscreen buffer is
   * associated. The offscreen buffers are always allocated for the toplevel
   * windows. However, painted is performed on lower-level heavyweight
   * components too, if they contain Swing components.
   *
   * @param root the heavyweight component to blit upon
   * @param rootRect the rectangle in the root component's coordinate space
   */
  private void blitBuffer(Component root, Rectangle rootRect)
  {
    if (! root.isShowing())
      return;

    // Find the Window from which we use the backbuffer.
    Component bufferRoot = root;
    Rectangle bufferRect = rootRect.getBounds();
    if (!(bufferRoot instanceof Window))
      {
        bufferRoot = SwingUtilities.getWindowAncestor(bufferRoot);
        SwingUtilities.convertRectangleToAncestor(root, rootRect, bufferRoot);
      }

    Graphics g = root.getGraphics();
    Image buffer = (Image) offscreenBuffers.get(bufferRoot);

    // Make sure we have a sane clip at this point.
    g.clipRect(rootRect.x, rootRect.y, rootRect.width, rootRect.height);
    g.drawImage(buffer, rootRect.x - bufferRect.x, rootRect.y - bufferRect.y,
                root);
    g.dispose();

  }

  /**
   * Finds and returns the nearest heavyweight parent for the specified
   * component. If the component isn't contained inside a heavyweight parent,
   * this returns null.
   *
   * @param comp the component
   *
   * @return the nearest heavyweight parent for the specified component or
   *         null if the component has no heavyweight ancestor
   */
  private Component getHeavyweightParent(Component comp)
  {
    while (comp != null && comp.isLightweight())
      comp = comp.getParent();
    return comp;
  }

  /**
   * Commits the queued up back buffers to screen all at once.
   */
  private void commitRemainingBuffers()
  {
    // We synchronize on dirtyComponents here because that is what
    // paintDirtyRegions also synchronizes on while painting.
    synchronized (dirtyComponents)
      {
        Set entrySet = commitRequests.entrySet();
        Iterator i = entrySet.iterator();
        while (i.hasNext())
          {
            Map.Entry entry = (Map.Entry) i.next();
            Component root = (Component) entry.getKey();
            Rectangle area = (Rectangle) entry.getValue();
            blitBuffer(root, area);
            i.remove();
          }
      }
  }

  /**
   * Creates and returns a volatile offscreen buffer for the specified
   * component that can be used as a double buffer. The returned image
   * is a {@link VolatileImage}. Its size will be <code>(proposedWidth,
   * proposedHeight)</code> except when the maximum double buffer size
   * has been set in this RepaintManager.
   *
   * @param comp the Component for which to create a volatile buffer
   * @param proposedWidth the proposed width of the buffer
   * @param proposedHeight the proposed height of the buffer
   *
   * @since 1.4
   *
   * @see VolatileImage
   */
  public Image getVolatileOffscreenBuffer(Component comp, int proposedWidth,
                                          int proposedHeight)
  {
    Component root = SwingUtilities.getWindowAncestor(comp);
    Image buffer = (Image) offscreenBuffers.get(root);
    if (buffer == null 
        || buffer.getWidth(null) < proposedWidth 
        || buffer.getHeight(null) < proposedHeight
        || !(buffer instanceof VolatileImage))
      {
        int width = Math.max(proposedWidth, root.getWidth());
        width = Math.min(doubleBufferMaximumSize.width, width);
        int height = Math.max(proposedHeight, root.getHeight());
        height = Math.min(doubleBufferMaximumSize.height, height);
        buffer = root.createVolatileImage(width, height);
        if (buffer != null)
          offscreenBuffers.put(root, buffer);
      }
    return buffer;
  }
  

  /**
   * Get the value of the {@link #doubleBufferMaximumSize} property.
   *
   * @return The current value of the property
   *
   * @see #setDoubleBufferMaximumSize
   */
  public Dimension getDoubleBufferMaximumSize()
  {
    return doubleBufferMaximumSize;
  }

  /**
   * Set the value of the {@link #doubleBufferMaximumSize} property.
   *
   * @param size The new value of the property
   *
   * @see #getDoubleBufferMaximumSize
   */
  public void setDoubleBufferMaximumSize(Dimension size)
  {
    doubleBufferMaximumSize = size;
  }

  /**
   * Set the value of the {@link #doubleBufferingEnabled} property.
   *
   * @param buffer The new value of the property
   *
   * @see #isDoubleBufferingEnabled
   */
  public void setDoubleBufferingEnabled(boolean buffer)
  {
    doubleBufferingEnabled = buffer;
  }

  /**
   * Get the value of the {@link #doubleBufferingEnabled} property.
   *
   * @return The current value of the property
   *
   * @see #setDoubleBufferingEnabled
   */
  public boolean isDoubleBufferingEnabled()
  {
    return doubleBufferingEnabled;
  }
  
  public String toString()
  {
    return "RepaintManager";
  }
}
