home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 14.6 KB | 456 lines |
- /*
- * @(#)RepaintManager.java 1.19 98/01/30
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
- package java.awt.swing;
-
- /**
- * @version 1.19 01/30/98
- * @author Arnaud Weber
- */
-
- import java.awt.*;
- import java.awt.event.*;
- import java.util.*;
- import java.applet.*;
-
- public class RepaintManager {
- Hashtable dirtyComponents;
- boolean doubleBufferingEnabled = true;
- Image doubleBuffer;
- Dimension doubleBufferMaxSize;
- Vector invalidComponents;
- Timer flushTimer;
- boolean actionPending;
- RepaintListener repaintListener = new RepaintListener(this);
-
- private static final Object repaintManagerKey = RepaintManager.class;
-
- /** Return the RepaintManager for the calling thread.
- * This method will maintain one RepaintManager per
- * thread group.
- */
- public static RepaintManager currentManager(JComponent comp) {
- RepaintManager result = (RepaintManager)
- SwingUtilities.appContextGet(repaintManagerKey);
- if(result == null) {
- result = new RepaintManager();
- SwingUtilities.appContextPut(repaintManagerKey, result);
- }
- return result;
- }
-
- /** Set the RepaintManager that should be used for the calling
- * thread. <b>aRepaintManager</b> will become the current RepaintManager
- * for the calling thread's thread group.
- */
- public static void setCurrentManager(RepaintManager aRepaintManager) {
- if (aRepaintManager != null) {
- SwingUtilities.appContextPut(repaintManagerKey, aRepaintManager);
- } else {
- SwingUtilities.appContextRemove(repaintManagerKey);
- }
- }
-
- /** Create a new RepaintManager instance. You rarely call this constructor.
- * directly. To get the default RepaintManager, use
- * RepaintManager.currentManager(JComponent) (normally "this").
- */
- public RepaintManager() {
- dirtyComponents = new Hashtable();
- doubleBufferMaxSize = Toolkit.getDefaultToolkit().getScreenSize();
- }
-
- void setupTimer() {
- if(flushTimer == null) {
- flushTimer = new Timer(0,repaintListener);
- flushTimer.setRepeats(false);
- flushTimer.setCoalesce(true);
- }
- if(flushTimer.isRunning())
- flushTimer.stop();
- flushTimer.start();
- //System.out.println("**** timer started *****" + TimerQueue.sharedInstance());
- }
-
- /* Add a component in the list of component with an invalid layout
- */
- public synchronized void addInvalidComponent(JComponent component) {
- Component validateRoot = null;
-
- for(Component c = component; c != null; c = c.getParent()) {
- if (c instanceof CellRendererPane) {
- return;
- }
- if ((c instanceof JComponent) && (((JComponent)c).isValidateRoot())) {
- validateRoot = c;
- }
- }
-
- if(validateRoot != null) {
- Component ic;
- int i,c;
-
- if(invalidComponents == null) {
- invalidComponents = new Vector();
- }
-
- for(i=0,c=invalidComponents.size();i<c;i++) {
- ic = (Component) invalidComponents.elementAt(i);
- if(ic == validateRoot)
- return;
- }
-
- invalidComponents.addElement(validateRoot);
- if(!actionPending) {
- actionPending = true;
- setupTimer();
- }
- }
- }
-
- /** Remove an invalid component **/
- public synchronized void removeInvalidComponent(JComponent component) {
- if(invalidComponents != null) {
- int index = invalidComponents.indexOf(component);
- if(index != -1) {
- invalidComponents.removeElementAt(index);
- }
- }
- }
- /** Add a component in the list of component that should be refreshed.
- * If aComponent already has some dirty region, the rectangle <b>(x,y,w,h)</b> will be
- * added to the region that should be redrawn.
- */
- public synchronized void addDirtyRegion(JComponent aComponent,int x,int y,int w,int h) {
- Rectangle r = null;
-
- if(w <= 0 || h <= 0)
- return;
-
- if(!aComponent.isShowing()) {
- return;
- }
-
- if(dirtyComponents == null)
- dirtyComponents = new Hashtable();
- else
- r = (Rectangle) dirtyComponents.get(aComponent);
-
- if(r == null) {
- r = new Rectangle(x,y,w,h);
- dirtyComponents.put(aComponent,r);
- } else
- SwingUtilities.computeUnion(x,y,w,h,r);
-
- if(!actionPending) {
- actionPending = true;
- setupTimer();
- }
- }
-
- /** Return the current dirty region for a component.
- * Return an empty rectangle if the component is not
- * dirty.
- */
- public Rectangle getDirtyRegion(JComponent aComponent) {
- Rectangle r = null;
- synchronized(this) {
- if(dirtyComponents != null)
- r = (Rectangle)dirtyComponents.get(aComponent);
- }
- if(r == null)
- return new Rectangle(0,0,0,0);
- else
- return new Rectangle(r);
- }
-
- /** Mark a component completely dirty. <b>aComponent</b> will be
- * completely painted during the next paintDirtyRegions() call.
- */
- public void markCompletelyDirty(JComponent aComponent) {
- addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE);
- }
-
- /** Mark a component completely clean. <b>aComponent</b> will not
- * get painted during the next paintDirtyRegions() call
- */
- public void markCompletelyClean(JComponent aComponent) {
- synchronized(this) {
- if(dirtyComponents != null)
- dirtyComponents.remove(aComponent);
- }
- }
-
- /** Convenience that returns true if <b>aComponent</b> 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.
- */
- public boolean isCompletelyDirty(JComponent aComponent) {
- Rectangle r;
-
- r = getDirtyRegion(aComponent);
- if(r.width == Integer.MAX_VALUE &&
- r.height == Integer.MAX_VALUE)
- return true;
- else
- return false;
- }
-
- public void repaintDirtyRegions() {
- // System.out.println("**** action performed ***** " + invalidComponents);
- synchronized(this) {
- actionPending = false;
- if(flushTimer != null)
- flushTimer.stop();
- }
- validateInvalidComponents();
- paintDirtyRegions();
- }
-
- /** Cause all invalide component to get validated **/
- public void validateInvalidComponents() {
- Vector ic;
- int i,c;
-
- synchronized(this) {
- if(invalidComponents == null)
- return;
- ic = invalidComponents;
- invalidComponents = null;
- }
-
- for(i=0,c=ic.size() ; i < c ; i++) {
- ((Component)ic.elementAt(i)).validate();
-
- }
- }
-
- /** Cause all the known dirty regions to be painted
- */
- public void paintDirtyRegions() {
- int i, count;
- Hashtable tmpDirtyComponents;
- Vector roots;
- JComponent dirtyComponent;
-
- /** Get all the dirty components at once.
- */
- synchronized(this) {
- if(dirtyComponents == null) {
- return;
- }
- tmpDirtyComponents = dirtyComponents;
- dirtyComponents = null;
- }
-
- count = tmpDirtyComponents.size();
-
- if (count == 0) {
- // System.out.println("No dirty component");
- return;
- }
-
- Rectangle rect;
- Rectangle localBounds;
- Enumeration keys;
-
- roots = new Vector(count);
- keys = tmpDirtyComponents.keys();
-
- while(keys.hasMoreElements()) {
- dirtyComponent = (JComponent) keys.nextElement();
- collectDirtyComponents(tmpDirtyComponents,dirtyComponent, roots);
- }
-
- count = roots.size();
- // System.out.println("roots size is " + count);
- for(i=0 ; i < count ; i++) {
- dirtyComponent = (JComponent) roots.elementAt(i);
- rect = (Rectangle) tmpDirtyComponents.get(dirtyComponent);
- // System.out.println("Should refresh :" + rect);
- localBounds = dirtyComponent.getBounds();
- localBounds.x = localBounds.y = 0;
- rect = rect.intersection(localBounds);
- //System.out.println("** paint of " + dirtyComponent + rect);
- dirtyComponent.paintImmediately(rect.x,rect.y,rect.width,rect.height);
- }
- }
-
- void collectDirtyComponents(Hashtable dirtyComponents,
- JComponent dirtyComponent,
- Vector roots) {
- int dx, dy, rootDx, rootDy;
- Component component, rootDirtyComponent,parent;
- Rectangle tmp;
- Rectangle cBounds;
- boolean opaqueAncestorFound = false;
-
- // 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;
-
- cBounds = dirtyComponent._bounds;
-
- dx = rootDx = 0;
- dy = rootDy = 0;
- tmp = new Rectangle((Rectangle) dirtyComponents.get(dirtyComponent));
-
- // System.out.println("Collect dirty component for bound " + tmp +
- // "component bounds is " + cBounds);;
- SwingUtilities.computeIntersection(0,0,cBounds.width,cBounds.height,tmp);
-
- if (tmp.isEmpty()) {
- // System.out.println("Empty 1");
- return;
- }
-
- if(dirtyComponent.isOpaque())
- opaqueAncestorFound = true;
-
- for(;;) {
- parent = component.getParent();
- if(parent == null)
- break;
-
- if(!(parent instanceof JComponent))
- break;
-
- component = parent;
-
- if(((JComponent)component).isOpaque())
- opaqueAncestorFound = true;
-
- dx += cBounds.x;
- dy += cBounds.y;
- tmp.setLocation(tmp.x + cBounds.x,
- tmp.y + cBounds.y);
-
- cBounds = ((JComponent)component)._bounds;
- tmp = SwingUtilities.computeIntersection(0,0,cBounds.width,cBounds.height,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.addElement(rootDirtyComponent);
- }
-
- public synchronized String toString() {
- StringBuffer sb = new StringBuffer();
- if(dirtyComponents != null)
- sb.append("" + dirtyComponents);
- return sb.toString();
- }
-
- /** Return the offscreen buffer that should be used as a double buffer with the component <code>c</code>
- * By default there is a double buffer per RepaintManager.
- * The buffer might be smaller than <code>(proposedWidth,proposedHeight)</code>
- * This happens when the maximum double buffer size as been set for the receiving
- * repaint manager.
- */
- public Image getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) {
- Image result;
- int width,height;
-
- if(proposedWidth > doubleBufferMaxSize.width)
- width = doubleBufferMaxSize.width;
- else
- width = proposedWidth;
-
- if(proposedHeight > doubleBufferMaxSize.height)
- height =doubleBufferMaxSize.height;
- else
- height = proposedHeight;
-
- if(doubleBuffer != null) {
- if(doubleBuffer.getWidth(null) < width ||
- doubleBuffer.getHeight(null) < height)
- doubleBuffer = null;
- }
-
- if(doubleBuffer == null) {
- doubleBuffer = c.createImage(width,height);
- // System.out.println("Creating offscreen buffer " + new Dimension(width,height));
- }
- return doubleBuffer;
- }
-
- /** Set the maximum double buffer size. **/
- public void setDoubleBufferMaximumSize(Dimension d) {
- doubleBufferMaxSize = d;
- if(doubleBuffer != null) {
- if(doubleBuffer.getWidth(null) > d.width ||
- doubleBuffer.getHeight(null) > d.height)
- doubleBuffer = null;
- }
- }
-
- public Dimension getDoubleBufferMaximumSize() {
- return doubleBufferMaxSize;
- }
-
- public void setDoubleBufferingEnabled(boolean aFlag) {
- doubleBufferingEnabled = aFlag;
- if(!doubleBufferingEnabled) {
- doubleBuffer = null;
- }
- }
-
- public boolean isDoubleBufferingEnabled() {
- return doubleBufferingEnabled;
- }
-
- static class RepaintListener implements ActionListener {
- RepaintManager manager;
-
- public RepaintListener(RepaintManager rp) {
- manager = rp;
- }
-
- public void actionPerformed(ActionEvent e) {
- manager.repaintDirtyRegions();
- }
- }
- }
-