123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861 |
- /* 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 gnu.classpath.SystemProperties;
- import gnu.java.awt.LowPriorityEvent;
- import java.applet.Applet;
- import java.awt.Component;
- import java.awt.Dimension;
- import java.awt.EventQueue;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.awt.Rectangle;
- import java.awt.Toolkit;
- import java.awt.Window;
- import java.awt.event.InvocationEvent;
- import java.awt.image.VolatileImage;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- 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>
- * 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
- {
- /**
- * An InvocationEvent subclass that implements LowPriorityEvent. This is used
- * to defer the execution of RepaintManager requests as long as possible on
- * the event queue. This way we make sure that all available input is
- * processed before getting active with the RepaintManager. This allows
- * for better optimization (more validate and repaint requests can be
- * coalesced) and thus has a positive effect on performance for GUI
- * applications under heavy load.
- */
- private static class RepaintWorkerEvent
- extends InvocationEvent
- implements LowPriorityEvent
- {
- /**
- * Creates a new RepaintManager event.
- *
- * @param source the source
- * @param runnable the runnable to execute
- */
- public RepaintWorkerEvent(Object source, Runnable runnable,
- Object notifier, boolean catchEx)
- {
- super(source, runnable, notifier, catchEx);
- }
- /**
- * An application that I met implements its own event dispatching and
- * calls dispatch() via reflection, and only checks declared methods,
- * that is, it expects this method to be in the event's class, not
- * in a superclass. So I put this in here... sigh.
- */
- public void dispatch()
- {
- super.dispatch();
- }
- }
- /**
- * 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;
- /**
- * 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 =
- SystemProperties.getProperty("gnu.swing.doublebuffering", "true")
- .equals("true");
- offscreenBuffers = new WeakHashMap();
- }
- /**
- * 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);
- 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.computeVisibleRect(rectCache);
- SwingUtilities.computeIntersection(x, y, w, h, rectCache);
- if (! rectCache.isEmpty())
- {
- synchronized (dirtyComponents)
- {
- Rectangle dirtyRect = (Rectangle)dirtyComponents.get(component);
- if (dirtyRect != null)
- {
- SwingUtilities.computeUnion(rectCache.x, rectCache.y,
- rectCache.width, rectCache.height,
- dirtyRect);
- }
- else
- {
- dirtyComponents.put(component, rectCache.getBounds());
- }
- }
- if (! repaintWorker.isLive())
- {
- repaintWorker.setLive(true);
- 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 circuit 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);
- }
- 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();
- }
- /**
- * Compiles a list of components that really get repainted. This is called
- * once for each component in the dirtyRegions 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;
- // This will contain the dirty region in the root coordinate system,
- // possibly clipped by ancestor's bounds.
- Rectangle originalDirtyRect = (Rectangle) dirtyRegions.get(dirty);
- rectCache.setBounds(originalDirtyRect);
- // The bounds of the current component.
- int x = dirty.getX();
- int y = dirty.getY();
- int w = dirty.getWidth();
- int h = dirty.getHeight();
- // Do nothing if dirty region is clipped away by the component's bounds.
- rectCache = SwingUtilities.computeIntersection(0, 0, w, h, rectCache);
- if (rectCache.isEmpty())
- return;
- // The cumulated offsets.
- int dx = 0;
- int dy = 0;
- // The actual offset for the found root.
- int rootDx = 0;
- int rootDy = 0;
- // 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;
- // Update the offset.
- dx += x;
- dy += y;
- rectCache.x += x;
- rectCache.y += y;
- x = current.getX();
- y = current.getY();
- w = current.getWidth();
- h = current.getHeight();
- rectCache = SwingUtilities.computeIntersection(0, 0, w, h, rectCache);
- // Don't paint if the dirty regions is clipped away by any of
- // its ancestors.
- if (rectCache.isEmpty())
- return;
- // We can skip to the next up when this parent is not dirty.
- if (dirtyRegions.containsKey(parent))
- {
- root = current;
- rootDx = dx;
- rootDy = dy;
- }
- }
- // Merge the rectangles of the root and the requested component if
- // the are different.
- if (root != dirty)
- {
- rectCache.x += rootDx - dx;
- rectCache.y += rootDy - dy;
- Rectangle dirtyRect = (Rectangle) dirtyRegions.get(root);
- SwingUtilities.computeUnion(rectCache.x, rectCache.y, rectCache.width,
- rectCache.height, dirtyRect);
- }
- // Adds the root to the roots set.
- if (! roots.contains(root))
- 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 = component.createImage(width, height);
- offscreenBuffers.put(root, buffer);
- }
- return buffer;
- }
- /**
- * Blits the back buffer of the specified root component to the screen.
- * This is package private because it must get called by JComponent.
- *
- * @param comp the component to be painted
- * @param x the area to paint on screen, in comp coordinates
- * @param y the area to paint on screen, in comp coordinates
- * @param w the area to paint on screen, in comp coordinates
- * @param h the area to paint on screen, in comp coordinates
- */
- void commitBuffer(Component comp, int x, int y, int w, int h)
- {
- Component root = comp;
- while (root != null
- && ! (root instanceof Window || root instanceof Applet))
- {
- x += root.getX();
- y += root.getY();
- root = root.getParent();
- }
- if (root != null)
- {
- Graphics g = root.getGraphics();
- Image buffer = (Image) offscreenBuffers.get(root);
- if (buffer != null)
- {
- // Make sure we have a sane clip at this point.
- g.clipRect(x, y, w, h);
- g.drawImage(buffer, 0, 0, root);
- g.dispose();
- }
- }
- }
- /**
- * 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";
- }
- /**
- * Sends an RepaintManagerEvent to the event queue with the specified
- * runnable. This is similar to SwingUtilities.invokeLater(), only that the
- * event is a low priority event in order to defer the execution a little
- * more.
- */
- private void invokeLater(Runnable runnable)
- {
- Toolkit tk = Toolkit.getDefaultToolkit();
- EventQueue evQueue = tk.getSystemEventQueue();
- InvocationEvent ev = new RepaintWorkerEvent(evQueue, runnable, null, false);
- evQueue.postEvent(ev);
- }
- }
|