1 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 ; 15 import java.util.*; 16 import java.applet.*; 17 18 import sun.security.action.GetPropertyAction; 19 20 21 29 public class RepaintManager 30 { 31 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 49 DoubleBufferInfo standardDoubleBuffer; 52 53 private static final Object repaintManagerKey = RepaintManager .class; 54 55 static boolean volatileImageBufferEnabled = true; 57 58 static final int VOLATILE_LOOP_MAX = 2; 61 62 static { 63 String vib = (String ) java.security.AccessController.doPrivileged( 64 new GetPropertyAction("swing.volatileImageBufferEnabled")); 65 volatileImageBufferEnabled = (vib == null || vib.equals("true")); 66 } 67 68 76 public static RepaintManager currentManager(Component c) { 77 RepaintManager result = (RepaintManager ) SwingUtilities.appContextGet(repaintManagerKey); 82 if(result == null) { 83 result = new RepaintManager (); 84 SwingUtilities.appContextPut(repaintManagerKey, result); 85 } 86 return result; 87 } 88 89 99 public static RepaintManager currentManager(JComponent c) { 100 return currentManager((Component)c); 101 } 102 103 104 110 public static void setCurrentManager(RepaintManager aRepaintManager) { 111 if (aRepaintManager != null) { 112 SwingUtilities.appContextPut(repaintManagerKey, aRepaintManager); 113 } else { 114 SwingUtilities.appContextRemove(repaintManagerKey); 115 } 116 } 117 118 123 public RepaintManager() { 124 Object dbe = java.security.AccessController.doPrivileged( 125 new GetPropertyAction("awt.nativeDoubleBuffering")); 126 boolean nativeDoubleBuffering = (dbe != null) ? 127 Boolean.valueOf(dbe.toString()).booleanValue() : false; 128 doubleBufferingEnabled = !nativeDoubleBuffering; 131 } 132 133 134 142 public synchronized void addInvalidComponent(JComponent invalidComponent) 143 { 144 Component validateRoot = null; 145 146 149 for(Component c = invalidComponent; c != null; c = c.getParent()) { 150 if ((c instanceof CellRendererPane ) || (c.getPeer() == null)) { 151 return; 152 } 153 if ((c instanceof JComponent ) && (((JComponent )c).isValidateRoot())) { 154 validateRoot = c; 155 break; 156 } 157 } 158 159 161 if (validateRoot == null) { 162 return; 163 } 164 165 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 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 205 SystemEventQueueUtilities.queueComponentWorkRequest(root); 206 } 207 208 209 214 public synchronized void removeInvalidComponent(JComponent 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 231 public void addDirtyRegion(JComponent c, int x, int y, int w, int h) 232 { 233 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 return; 247 } 248 249 255 Component root = null; 256 257 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 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 return; 284 } 285 dirtyComponents.put(c, new Rectangle(x, y, w, h)); 286 } 287 288 291 SystemEventQueueUtilities.queueComponentWorkRequest(root); 292 } 293 294 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 SwingUtilities.computeUnion(x, y, w, h, r); 308 return true; 309 } 310 return false; 311 } 312 313 317 public Rectangle getDirtyRegion(JComponent 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 332 public void markCompletelyDirty(JComponent aComponent) { 333 addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE); 334 } 335 336 340 public void markCompletelyClean(JComponent aComponent) { 341 synchronized(this) { 342 dirtyComponents.remove(aComponent); 343 } 344 } 345 346 352 public boolean isCompletelyDirty(JComponent 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 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 389 public void paintDirtyRegions() { 390 int i, count; 391 Vector roots; 392 JComponent dirtyComponent; 393 394 synchronized(this) { 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 ) keys.nextElement(); 418 collectDirtyComponents(tmpDirtyComponents, dirtyComponent, roots); 419 } 420 421 count = roots.size(); 422 for(i=0 ; i < count ; i++) { 424 dirtyComponent = (JComponent ) roots.elementAt(i); 425 rect = (Rectangle) tmpDirtyComponents.get(dirtyComponent); 426 localBoundsH = dirtyComponent.getHeight(); 428 localBoundsW = dirtyComponent.getWidth(); 429 430 SwingUtilities.computeIntersection(localBoundsX, 431 localBoundsY, 432 localBoundsW, 433 localBoundsH, 434 rect); 435 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 ((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 dirtyComponent, 461 Vector roots) { 462 int dx, dy, rootDx, rootDy; 463 Component component, rootDirtyComponent,parent; 464 Rectangle cBounds; 466 467 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 SwingUtilities.computeIntersection(0,0,w,h,tmp); 487 488 if (tmp.isEmpty()) { 489 return; 491 } 492 493 for(;;) { 494 parent = component.getParent(); 495 if(parent == null) 496 break; 497 498 if(!(parent instanceof JComponent )) 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 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 536 if (!roots.contains(rootDirtyComponent)) 537 roots.addElement(rootDirtyComponent); 538 } 539 540 541 547 public synchronized String toString() { 548 StringBuffer sb = new StringBuffer (); 549 if(dirtyComponents != null) 550 sb.append("" + dirtyComponents); 551 return sb.toString(); 552 } 553 554 555 563 public Image getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) { 564 return _getOffscreenBuffer(c, proposedWidth, proposedHeight); 565 } 566 567 579 public Image 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 image = (VolatileImage )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 _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 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 ) { 636 ((JComponent )c).setCreatedDoubleBuffer(true); 637 doubleBuffer.image = result; 638 } 639 } 644 return result; 645 } 646 647 648 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 Iterator gcs = volatileMap.keySet().iterator(); 659 while (gcs.hasNext()) { 660 GraphicsConfiguration gc = (GraphicsConfiguration)gcs.next(); 661 VolatileImage image = (VolatileImage )volatileMap.get(gc); 662 if (image.getWidth() > d.width || image.getHeight() > d.height) { 663 image.flush(); 664 gcs.remove(); 665 } 666 } 667 } 668 669 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 694 public void setDoubleBufferingEnabled(boolean aFlag) { 695 doubleBufferingEnabled = aFlag; 696 } 697 698 709 public boolean isDoubleBufferingEnabled() { 710 return doubleBufferingEnabled; 711 } 712 713 718 void resetDoubleBuffer() { 719 if (standardDoubleBuffer != null) { 720 standardDoubleBuffer.needsReset = true; 721 } 722 } 723 724 727 void resetVolatileDoubleBuffer(GraphicsConfiguration gc) { 728 Image image = (Image )volatileMap.remove(gc); 729 if (image != null) { 730 image.flush(); 731 } 732 } 733 734 738 boolean useVolatileDoubleBuffer() { 739 return volatileImageBufferEnabled; 740 } 741 742 private class DoubleBufferInfo { 743 public Image image; 744 public Dimension size; 745 public boolean needsReset = false; 746 } 747 } 748 | Popular Tags |