/[classpath]/classpath/javax/swing/RepaintManager.java
ViewVC logotype

Diff of /classpath/javax/swing/RepaintManager.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6.2.7 by gnu_andrew, Tue Sep 20 18:46:32 2005 UTC revision 1.6.2.8 by gnu_andrew, Wed Nov 2 00:43:48 2005 UTC
# Line 1  Line 1 
1  /* RepaintManager.java --  /* RepaintManager.java --
2     Copyright (C) 2002, 2004  Free Software Foundation, Inc.     Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 43  import java.awt.Dimension; Line 43  import java.awt.Dimension;
43  import java.awt.Image;  import java.awt.Image;
44  import java.awt.Rectangle;  import java.awt.Rectangle;
45  import java.awt.image.VolatileImage;  import java.awt.image.VolatileImage;
46  import java.util.Enumeration;  import java.util.ArrayList;
47    import java.util.Collections;
48    import java.util.Comparator;
49  import java.util.HashMap;  import java.util.HashMap;
 import java.util.Hashtable;  
50  import java.util.Iterator;  import java.util.Iterator;
 import java.util.Map;  
 import java.util.Vector;  
51    
52  /**  /**
53   * <p>The repaint manager holds a set of dirty regions, invalid components,   * <p>The repaint manager holds a set of dirty regions, invalid components,
# Line 111  public class RepaintManager Line 110  public class RepaintManager
110    
111    }    }
112    
113      /**
114       * Compares two components using their depths in the component hierarchy.
115       * A component with a lesser depth (higher level components) are sorted
116       * before components with a deeper depth (low level components). This is used
117       * to order paint requests, so that the higher level components are painted
118       * before the low level components get painted.
119       *
120       * @author Roman Kennke (kennke@aicas.com)
121       */
122      private class ComponentComparator implements Comparator
123      {
124    
125        /**
126         * Compares two components.
127         *
128         * @param o1 the first component
129         * @param o2 the second component
130         *
131         * @return a negative integer, if <code>o1</code> is higher in the
132         *         hierarchy than <code>o2</code>, zero, if both are at the same
133         *         level and a positive integer, if <code>o1</code> is deeper in
134         *         the hierarchy than <code>o2</code>
135         */
136        public int compare(Object o1, Object o2)
137        {
138          if (o1 instanceof JComponent && o2 instanceof JComponent)
139            {
140              JComponent c1 = (JComponent) o1;
141              JComponent c2 = (JComponent) o2;
142              return getDepth(c1) - getDepth(c2);
143            }
144          else
145            throw new ClassCastException("This comparator can only be used with "
146                                         + "JComponents");
147        }
148    
149        /**
150         * Computes the depth for a given JComponent.
151         *
152         * @param c the component to compute the depth for
153         *
154         * @return the depth of the component
155         */
156        private int getDepth(JComponent c)
157        {
158          Component comp = c;
159          int depth = 0;
160          while (comp != null)
161            {
162              comp = comp.getParent();
163              depth++;
164            }
165          return depth;
166        }
167      }
168    
169    /**    /**
170     * A table storing the dirty regions of components.  The keys of this     * A table storing the dirty regions of components.  The keys of this
171     * table are components, the values are rectangles. Each component maps     * table are components, the values are rectangles. Each component maps
# Line 123  public class RepaintManager Line 178  public class RepaintManager
178     * @see #markCompletelyClean     * @see #markCompletelyClean
179     * @see #markCompletelyDirty     * @see #markCompletelyDirty
180     */     */
181    Hashtable dirtyComponents;    HashMap dirtyComponents;
182    
183      HashMap workDirtyComponents;
184    
185      /**
186       * Stores the order in which the components get repainted.
187       */
188      ArrayList repaintOrder;
189      ArrayList workRepaintOrder;
190    
191      /**
192       * The comparator used for ordered inserting into the repaintOrder list.
193       */
194      Comparator comparator;
195    
196    /**    /**
197     * A single, shared instance of the helper class. Any methods which mark     * A single, shared instance of the helper class. Any methods which mark
# Line 146  public class RepaintManager Line 214  public class RepaintManager
214     * @see #removeInvalidComponent     * @see #removeInvalidComponent
215     * @see #validateInvalidComponents     * @see #validateInvalidComponents
216     */     */
217    Vector invalidComponents;    ArrayList invalidComponents;
218      ArrayList workInvalidComponents;
219    
220    /**    /**
221     * Whether or not double buffering is enabled on this repaint     * Whether or not double buffering is enabled on this repaint
222     * manager. This is merely a hint to clients; the RepaintManager will     * manager. This is merely a hint to clients; the RepaintManager will
223     * always return an offscreen buffer when one is requested.     * always return an offscreen buffer when one is requested.
224     *     *
225     * @see #getDoubleBufferingEnabled     * @see #isDoubleBufferingEnabled
226     * @see #setDoubleBufferingEnabled     * @see #setDoubleBufferingEnabled
227     */     */
228    boolean doubleBufferingEnabled;    boolean doubleBufferingEnabled;
# Line 184  public class RepaintManager Line 253  public class RepaintManager
253     * components in all windows.  This is package-private to avoid an accessor     * components in all windows.  This is package-private to avoid an accessor
254     * method.     * method.
255     *     *
256     * @see #currentManager     * @see #currentManager(JComponent)
257     * @see #setCurrentManager     * @see #setCurrentManager
258     */     */
259    static RepaintManager globalManager;    static RepaintManager globalManager;
# Line 194  public class RepaintManager Line 263  public class RepaintManager
263     */     */
264    public RepaintManager()    public RepaintManager()
265    {    {
266      dirtyComponents = new Hashtable();      dirtyComponents = new HashMap();
267      invalidComponents = new Vector();      workDirtyComponents = new HashMap();
268        repaintOrder = new ArrayList();
269        workRepaintOrder = new ArrayList();
270        invalidComponents = new ArrayList();
271        workInvalidComponents = new ArrayList();
272      repaintWorker = new RepaintWorker();      repaintWorker = new RepaintWorker();
273      doubleBufferMaximumSize = new Dimension(2000,2000);      doubleBufferMaximumSize = new Dimension(2000,2000);
274      doubleBufferingEnabled = true;      doubleBufferingEnabled = true;
# Line 291  public class RepaintManager Line 364  public class RepaintManager
364     */     */
365    public synchronized void removeInvalidComponent(JComponent component)    public synchronized void removeInvalidComponent(JComponent component)
366    {    {
367      invalidComponents.removeElement(component);      invalidComponents.remove(component);
368    }    }
369    
370    /**    /**
# Line 315  public class RepaintManager Line 388  public class RepaintManager
388    public synchronized void addDirtyRegion(JComponent component, int x, int y,    public synchronized void addDirtyRegion(JComponent component, int x, int y,
389                                            int w, int h)                                            int w, int h)
390    {    {
391      if (w == 0 || h == 0)      if (w == 0 || h == 0 || !component.isShowing())
392        return;        return;
   
393      Rectangle r = new Rectangle(x, y, w, h);      Rectangle r = new Rectangle(x, y, w, h);
394      if (dirtyComponents.containsKey(component))      if (dirtyComponents.containsKey(component))
395        r = r.union((Rectangle)dirtyComponents.get(component));        r = r.union((Rectangle)dirtyComponents.get(component));
396        else
397          insertInRepaintOrder(component);
398      dirtyComponents.put(component, r);      dirtyComponents.put(component, r);
399      if (! repaintWorker.isLive())      if (! repaintWorker.isLive())
400        {        {
# Line 328  public class RepaintManager Line 402  public class RepaintManager
402          SwingUtilities.invokeLater(repaintWorker);          SwingUtilities.invokeLater(repaintWorker);
403        }        }
404    }    }
405      
406      /**
407       * Inserts a component into the repaintOrder list in an ordered fashion,
408       * using a binary search.
409       *
410       * @param c the component to be inserted
411       */
412      private void insertInRepaintOrder(JComponent c)
413      {
414        if (comparator == null)
415          comparator = new ComponentComparator();
416        int insertIndex = Collections.binarySearch(repaintOrder, c, comparator);
417        if (insertIndex < 0)
418          insertIndex = -(insertIndex + 1);
419        repaintOrder.add(insertIndex, c);
420      }
421    
422    /**    /**
423     * Get the dirty region associated with a component, or <code>null</code>     * Get the dirty region associated with a component, or <code>null</code>
424     * if the component has no dirty region.     * if the component has no dirty region.
# Line 345  public class RepaintManager Line 435  public class RepaintManager
435     */     */
436    public Rectangle getDirtyRegion(JComponent component)    public Rectangle getDirtyRegion(JComponent component)
437    {    {
438      return (Rectangle) dirtyComponents.get(component);      Rectangle dirty = (Rectangle) dirtyComponents.get(component);
439        if (dirty == null)
440          dirty = new Rectangle();
441        return dirty;
442    }    }
443        
444    /**    /**
# Line 363  public class RepaintManager Line 456  public class RepaintManager
456    {    {
457      Rectangle r = component.getBounds();      Rectangle r = component.getBounds();
458      addDirtyRegion(component, r.x, r.y, r.width, r.height);      addDirtyRegion(component, r.x, r.y, r.width, r.height);
459        component.isCompletelyDirty = true;
460    }    }
461    
462    /**    /**
# Line 378  public class RepaintManager Line 472  public class RepaintManager
472     */     */
473    public void markCompletelyClean(JComponent component)    public void markCompletelyClean(JComponent component)
474    {    {
475      dirtyComponents.remove(component);      synchronized (this)
476          {
477            dirtyComponents.remove(component);
478          }
479        component.isCompletelyDirty = false;
480    }    }
481    
482    /**    /**
# Line 397  public class RepaintManager Line 495  public class RepaintManager
495     */     */
496    public boolean isCompletelyDirty(JComponent component)    public boolean isCompletelyDirty(JComponent component)
497    {    {
498      Rectangle dirty = (Rectangle) dirtyComponents.get(component);      if (! dirtyComponents.containsKey(component))
     if (dirty == null)  
499        return false;        return false;
500      Rectangle r = component.getBounds();      return component.isCompletelyDirty;
     if (r == null)  
       return true;  
     return dirty.contains(r);  
501    }    }
502    
503    /**    /**
# Line 412  public class RepaintManager Line 506  public class RepaintManager
506     */     */
507    public void validateInvalidComponents()    public void validateInvalidComponents()
508    {    {
509      for (Enumeration e = invalidComponents.elements(); e.hasMoreElements(); )      // In order to keep the blocking of application threads minimal, we switch
510        // the invalidComponents field with the workInvalidComponents field and
511        // work with the workInvalidComponents field.
512        synchronized(this)
513        {
514          ArrayList swap = invalidComponents;
515          invalidComponents = workInvalidComponents;
516          workInvalidComponents = swap;
517        }
518        for (Iterator i = workInvalidComponents.iterator(); i.hasNext(); )
519        {        {
520          JComponent comp = (JComponent) e.nextElement();          JComponent comp = (JComponent) i.next();
521          if (! (comp.isVisible() && comp.isShowing()))          if (! (comp.isVisible() && comp.isShowing()))
522            continue;            continue;
523          comp.validate();          comp.validate();
524        }        }
525      invalidComponents.clear();      workInvalidComponents.clear();
526    }    }
527    
528    /**    /**
529     * Repaint all regions of all components which have been marked dirty in     * Repaint all regions of all components which have been marked dirty in
530     * the {@link #dirtyComponents} table.     * the {@link #dirtyComponents} table.
531     */     */
532    public void paintDirtyRegions()    public synchronized void paintDirtyRegions()
533    {    {
534      // step 1: pull out roots and calculate spanning damage      // In order to keep the blocking of application threads minimal, we switch
535        // the dirtyComponents field with the workdirtyComponents field and the
536      HashMap roots = new HashMap();      // repaintOrder field with the workRepaintOrder field and work with the
537      for (Enumeration e = dirtyComponents.keys(); e.hasMoreElements(); )      // work* fields.
538        synchronized(this)
539        {
540          ArrayList swap = workRepaintOrder;
541          workRepaintOrder = repaintOrder;
542          repaintOrder = swap;
543          HashMap swap2 = workDirtyComponents;
544          workDirtyComponents = dirtyComponents;
545          dirtyComponents = swap2;
546        }
547        for (Iterator i = workRepaintOrder.iterator(); i.hasNext();)
548        {        {
549          JComponent comp = (JComponent) e.nextElement();          JComponent comp = (JComponent) i.next();
550          if (! (comp.isVisible() && comp.isShowing()))          // If a component is marked completely clean in the meantime, then skip
551            // it.
552            Rectangle damaged = (Rectangle) workDirtyComponents.get(comp);
553            if (damaged == null || damaged.isEmpty())
554            continue;            continue;
555          Rectangle damaged = getDirtyRegion(comp);          comp.paintImmediately(damaged);
         if (damaged.width == 0 || damaged.height == 0)  
           continue;  
         JRootPane root = comp.getRootPane();  
         // If the component has no root, no repainting will occur.  
         if (root == null)  
           continue;  
         Rectangle rootDamage = SwingUtilities.convertRectangle(comp, damaged, root);  
         if (! roots.containsKey(root))  
           {  
             roots.put(root, rootDamage);  
           }  
         else  
           {  
             roots.put(root, ((Rectangle)roots.get(root)).union(rootDamage));  
           }  
       }  
     dirtyComponents.clear();  
   
     // step 2: paint those roots  
     Iterator i = roots.entrySet().iterator();  
     while(i.hasNext())  
       {  
         Map.Entry ent = (Map.Entry) i.next();  
         JRootPane root = (JRootPane) ent.getKey();  
         Rectangle rect = (Rectangle) ent.getValue();  
         root.paintImmediately(rect);                      
556        }        }
557        workRepaintOrder.clear();
558        workDirtyComponents.clear();
559    }    }
560    
561    /**    /**

Legend:
Removed from v.1.6.2.7  
changed lines
  Added in v.1.6.2.8

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26