GNU Classpath (0.91) | |
Frames | No Frames |
1: /* RepaintManager.java -- 2: Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing; 40: 41: import java.applet.Applet; 42: import java.awt.Component; 43: import java.awt.Dimension; 44: import java.awt.Graphics; 45: import java.awt.Image; 46: import java.awt.Rectangle; 47: import java.awt.Window; 48: import java.awt.image.VolatileImage; 49: import java.util.ArrayList; 50: import java.util.Collections; 51: import java.util.Comparator; 52: import java.util.HashMap; 53: import java.util.Iterator; 54: import java.util.Map; 55: import java.util.Set; 56: import java.util.WeakHashMap; 57: 58: /** 59: * <p>The repaint manager holds a set of dirty regions, invalid components, 60: * and a double buffer surface. The dirty regions and invalid components 61: * are used to coalesce multiple revalidate() and repaint() calls in the 62: * component tree into larger groups to be refreshed "all at once"; the 63: * double buffer surface is used by root components to paint 64: * themselves.</p> 65: * 66: * <p>In general, painting is very confusing in swing. see <a 67: * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">this 68: * document</a> for more details.</p> 69: * 70: * @author Roman Kennke (kennke@aicas.com) 71: * @author Graydon Hoare (graydon@redhat.com) 72: */ 73: public class RepaintManager 74: { 75: /** 76: * The current repaint managers, indexed by their ThreadGroups. 77: */ 78: private static WeakHashMap currentRepaintManagers; 79: 80: /** 81: * A rectangle object to be reused in damaged regions calculation. 82: */ 83: private static Rectangle rectCache = new Rectangle(); 84: 85: /** 86: * <p>A helper class which is placed into the system event queue at 87: * various times in order to facilitate repainting and layout. There is 88: * typically only one of these objects active at any time. When the 89: * {@link RepaintManager} is told to queue a repaint, it checks to see if 90: * a {@link RepaintWorker} is "live" in the system event queue, and if 91: * not it inserts one using {@link SwingUtilities#invokeLater}.</p> 92: * 93: * <p>When the {@link RepaintWorker} comes to the head of the system 94: * event queue, its {@link RepaintWorker#run} method is executed by the 95: * swing paint thread, which revalidates all invalid components and 96: * repaints any damage in the swing scene.</p> 97: */ 98: private class RepaintWorker 99: implements Runnable 100: { 101: 102: boolean live; 103: 104: public RepaintWorker() 105: { 106: live = false; 107: } 108: 109: public synchronized void setLive(boolean b) 110: { 111: live = b; 112: } 113: 114: public synchronized boolean isLive() 115: { 116: return live; 117: } 118: 119: public void run() 120: { 121: try 122: { 123: ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); 124: RepaintManager rm = 125: (RepaintManager) currentRepaintManagers.get(threadGroup); 126: rm.validateInvalidComponents(); 127: rm.paintDirtyRegions(); 128: } 129: finally 130: { 131: setLive(false); 132: } 133: } 134: 135: } 136: 137: /** 138: * Compares two components using their depths in the component hierarchy. 139: * A component with a lesser depth (higher level components) are sorted 140: * before components with a deeper depth (low level components). This is used 141: * to order paint requests, so that the higher level components are painted 142: * before the low level components get painted. 143: * 144: * @author Roman Kennke (kennke@aicas.com) 145: */ 146: private class ComponentComparator implements Comparator 147: { 148: 149: /** 150: * Compares two components. 151: * 152: * @param o1 the first component 153: * @param o2 the second component 154: * 155: * @return a negative integer, if <code>o1</code> is bigger in than 156: * <code>o2</code>, zero, if both are at the same size and a 157: * positive integer, if <code>o1</code> is smaller than 158: * <code>o2</code> 159: */ 160: public int compare(Object o1, Object o2) 161: { 162: if (o1 instanceof JComponent && o2 instanceof JComponent) 163: { 164: JComponent c1 = (JComponent) o1; 165: Rectangle d1 = (Rectangle) dirtyComponentsWork.get(c1); 166: JComponent c2 = (JComponent) o2; 167: Rectangle d2 = (Rectangle) dirtyComponentsWork.get(c2); 168: return d2.width * d2.height - d1.width * d1.height; 169: } 170: throw new ClassCastException("This comparator can only be used with " 171: + "JComponents"); 172: } 173: } 174: 175: /** 176: * A table storing the dirty regions of components. The keys of this 177: * table are components, the values are rectangles. Each component maps 178: * to exactly one rectangle. When more regions are marked as dirty on a 179: * component, they are union'ed with the existing rectangle. 180: * 181: * This is package private to avoid a synthetic accessor method in inner 182: * class. 183: * 184: * @see #addDirtyRegion 185: * @see #getDirtyRegion 186: * @see #isCompletelyDirty 187: * @see #markCompletelyClean 188: * @see #markCompletelyDirty 189: */ 190: HashMap dirtyComponents; 191: 192: /** 193: * The dirtyComponents which is used in paintDiryRegions to avoid unnecessary 194: * locking. 195: */ 196: HashMap dirtyComponentsWork; 197: 198: /** 199: * The comparator used for ordered inserting into the repaintOrder list. 200: */ 201: private transient Comparator comparator; 202: 203: /** 204: * A single, shared instance of the helper class. Any methods which mark 205: * components as invalid or dirty eventually activate this instance. It 206: * is added to the event queue if it is not already active, otherwise 207: * reused. 208: * 209: * @see #addDirtyRegion 210: * @see #addInvalidComponent 211: */ 212: private RepaintWorker repaintWorker; 213: 214: /** 215: * The set of components which need revalidation, in the "layout" sense. 216: * There is no additional information about "what kind of layout" they 217: * need (as there is with dirty regions), so it is just a vector rather 218: * than a table. 219: * 220: * @see #addInvalidComponent 221: * @see #removeInvalidComponent 222: * @see #validateInvalidComponents 223: */ 224: private ArrayList invalidComponents; 225: 226: /** 227: * Whether or not double buffering is enabled on this repaint 228: * manager. This is merely a hint to clients; the RepaintManager will 229: * always return an offscreen buffer when one is requested. 230: * 231: * @see #isDoubleBufferingEnabled 232: * @see #setDoubleBufferingEnabled 233: */ 234: private boolean doubleBufferingEnabled; 235: 236: /** 237: * The offscreen buffers. This map holds one offscreen buffer per 238: * Window/Applet and releases them as soon as the Window/Applet gets garbage 239: * collected. 240: */ 241: private WeakHashMap offscreenBuffers; 242: 243: /** 244: * Indicates if the RepaintManager is currently repainting an area. 245: */ 246: private boolean repaintUnderway; 247: 248: /** 249: * This holds buffer commit requests when the RepaintManager is working. 250: * This maps Component objects (the top level components) to Rectangle 251: * objects (the area of the corresponding buffer that must be blitted on 252: * the component). 253: */ 254: private HashMap commitRequests; 255: 256: /** 257: * The maximum width and height to allocate as a double buffer. Requests 258: * beyond this size are ignored. 259: * 260: * @see #paintDirtyRegions 261: * @see #getDoubleBufferMaximumSize 262: * @see #setDoubleBufferMaximumSize 263: */ 264: private Dimension doubleBufferMaximumSize; 265: 266: 267: /** 268: * Create a new RepaintManager object. 269: */ 270: public RepaintManager() 271: { 272: dirtyComponents = new HashMap(); 273: dirtyComponentsWork = new HashMap(); 274: invalidComponents = new ArrayList(); 275: repaintWorker = new RepaintWorker(); 276: doubleBufferMaximumSize = new Dimension(2000,2000); 277: doubleBufferingEnabled = true; 278: offscreenBuffers = new WeakHashMap(); 279: repaintUnderway = false; 280: commitRequests = new HashMap(); 281: } 282: 283: /** 284: * Returns the <code>RepaintManager</code> for the current thread's 285: * thread group. The default implementation ignores the 286: * <code>component</code> parameter and returns the same repaint manager 287: * for all components. 288: * 289: * @param component a component to look up the manager of 290: * 291: * @return the current repaint manager for the calling thread's thread group 292: * and the specified component 293: * 294: * @see #setCurrentManager 295: */ 296: public static RepaintManager currentManager(Component component) 297: { 298: if (currentRepaintManagers == null) 299: currentRepaintManagers = new WeakHashMap(); 300: ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); 301: RepaintManager currentManager = 302: (RepaintManager) currentRepaintManagers.get(threadGroup); 303: if (currentManager == null) 304: { 305: currentManager = new RepaintManager(); 306: currentRepaintManagers.put(threadGroup, currentManager); 307: } 308: return currentManager; 309: } 310: 311: /** 312: * Returns the <code>RepaintManager</code> for the current thread's 313: * thread group. The default implementation ignores the 314: * <code>component</code> parameter and returns the same repaint manager 315: * for all components. 316: * 317: * This method is only here for backwards compatibility with older versions 318: * of Swing and simply forwards to {@link #currentManager(Component)}. 319: * 320: * @param component a component to look up the manager of 321: * 322: * @return the current repaint manager for the calling thread's thread group 323: * and the specified component 324: * 325: * @see #setCurrentManager 326: */ 327: public static RepaintManager currentManager(JComponent component) 328: { 329: return currentManager((Component)component); 330: } 331: 332: /** 333: * Sets the repaint manager for the calling thread's thread group. 334: * 335: * @param manager the repaint manager to set for the current thread's thread 336: * group 337: * 338: * @see #currentManager(Component) 339: */ 340: public static void setCurrentManager(RepaintManager manager) 341: { 342: if (currentRepaintManagers == null) 343: currentRepaintManagers = new WeakHashMap(); 344: 345: ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); 346: currentRepaintManagers.put(threadGroup, manager); 347: } 348: 349: /** 350: * Add a component to the {@link #invalidComponents} vector. If the 351: * {@link #repaintWorker} class is not active, insert it in the system 352: * event queue. 353: * 354: * @param component The component to add 355: * 356: * @see #removeInvalidComponent 357: */ 358: public void addInvalidComponent(JComponent component) 359: { 360: Component ancestor = component; 361: 362: while (ancestor != null 363: && (! (ancestor instanceof JComponent) 364: || ! ((JComponent) ancestor).isValidateRoot() )) 365: ancestor = ancestor.getParent(); 366: 367: if (ancestor != null 368: && ancestor instanceof JComponent 369: && ((JComponent) ancestor).isValidateRoot()) 370: component = (JComponent) ancestor; 371: 372: if (invalidComponents.contains(component)) 373: return; 374: 375: synchronized (invalidComponents) 376: { 377: invalidComponents.add(component); 378: } 379: 380: if (! repaintWorker.isLive()) 381: { 382: repaintWorker.setLive(true); 383: SwingUtilities.invokeLater(repaintWorker); 384: } 385: } 386: 387: /** 388: * Remove a component from the {@link #invalidComponents} vector. 389: * 390: * @param component The component to remove 391: * 392: * @see #addInvalidComponent 393: */ 394: public void removeInvalidComponent(JComponent component) 395: { 396: synchronized (invalidComponents) 397: { 398: invalidComponents.remove(component); 399: } 400: } 401: 402: /** 403: * Add a region to the set of dirty regions for a specified component. 404: * This involves union'ing the new region with any existing dirty region 405: * associated with the component. If the {@link #repaintWorker} class 406: * is not active, insert it in the system event queue. 407: * 408: * @param component The component to add a dirty region for 409: * @param x The left x coordinate of the new dirty region 410: * @param y The top y coordinate of the new dirty region 411: * @param w The width of the new dirty region 412: * @param h The height of the new dirty region 413: * 414: * @see #addDirtyRegion 415: * @see #getDirtyRegion 416: * @see #isCompletelyDirty 417: * @see #markCompletelyClean 418: * @see #markCompletelyDirty 419: */ 420: public void addDirtyRegion(JComponent component, int x, int y, 421: int w, int h) 422: { 423: if (w <= 0 || h <= 0 || !component.isShowing()) 424: return; 425: component.computeVisibleRect(rectCache); 426: SwingUtilities.computeIntersection(x, y, w, h, rectCache); 427: 428: if (! rectCache.isEmpty()) 429: { 430: if (dirtyComponents.containsKey(component)) 431: { 432: SwingUtilities.computeUnion(rectCache.x, rectCache.y, 433: rectCache.width, rectCache.height, 434: (Rectangle) dirtyComponents.get(component)); 435: } 436: else 437: { 438: synchronized (dirtyComponents) 439: { 440: dirtyComponents.put(component, rectCache.getBounds()); 441: } 442: } 443: 444: if (! repaintWorker.isLive()) 445: { 446: repaintWorker.setLive(true); 447: SwingUtilities.invokeLater(repaintWorker); 448: } 449: } 450: } 451: 452: /** 453: * Get the dirty region associated with a component, or <code>null</code> 454: * if the component has no dirty region. 455: * 456: * @param component The component to get the dirty region of 457: * 458: * @return The dirty region of the component 459: * 460: * @see #dirtyComponents 461: * @see #addDirtyRegion 462: * @see #isCompletelyDirty 463: * @see #markCompletelyClean 464: * @see #markCompletelyDirty 465: */ 466: public Rectangle getDirtyRegion(JComponent component) 467: { 468: Rectangle dirty = (Rectangle) dirtyComponents.get(component); 469: if (dirty == null) 470: dirty = new Rectangle(); 471: return dirty; 472: } 473: 474: /** 475: * Mark a component as dirty over its entire bounds. 476: * 477: * @param component The component to mark as dirty 478: * 479: * @see #dirtyComponents 480: * @see #addDirtyRegion 481: * @see #getDirtyRegion 482: * @see #isCompletelyDirty 483: * @see #markCompletelyClean 484: */ 485: public void markCompletelyDirty(JComponent component) 486: { 487: Rectangle r = component.getBounds(); 488: addDirtyRegion(component, r.x, r.y, r.width, r.height); 489: component.isCompletelyDirty = true; 490: } 491: 492: /** 493: * Remove all dirty regions for a specified component 494: * 495: * @param component The component to mark as clean 496: * 497: * @see #dirtyComponents 498: * @see #addDirtyRegion 499: * @see #getDirtyRegion 500: * @see #isCompletelyDirty 501: * @see #markCompletelyDirty 502: */ 503: public void markCompletelyClean(JComponent component) 504: { 505: synchronized (dirtyComponents) 506: { 507: dirtyComponents.remove(component); 508: } 509: component.isCompletelyDirty = false; 510: } 511: 512: /** 513: * Return <code>true</code> if the specified component is completely 514: * contained within its dirty region, otherwise <code>false</code> 515: * 516: * @param component The component to check for complete dirtyness 517: * 518: * @return Whether the component is completely dirty 519: * 520: * @see #dirtyComponents 521: * @see #addDirtyRegion 522: * @see #getDirtyRegion 523: * @see #isCompletelyDirty 524: * @see #markCompletelyClean 525: */ 526: public boolean isCompletelyDirty(JComponent component) 527: { 528: if (! dirtyComponents.containsKey(component)) 529: return false; 530: return component.isCompletelyDirty; 531: } 532: 533: /** 534: * Validate all components which have been marked invalid in the {@link 535: * #invalidComponents} vector. 536: */ 537: public void validateInvalidComponents() 538: { 539: // We don't use an iterator here because that would fail when there are 540: // components invalidated during the validation of others, which happens 541: // quite frequently. Instead we synchronize the access a little more. 542: while (invalidComponents.size() > 0) 543: { 544: Component comp; 545: synchronized (invalidComponents) 546: { 547: comp = (Component) invalidComponents.remove(0); 548: } 549: // Validate the validate component. 550: if (! (comp.isVisible() && comp.isShowing())) 551: continue; 552: comp.validate(); 553: } 554: } 555: 556: /** 557: * Repaint all regions of all components which have been marked dirty in 558: * the {@link #dirtyComponents} table. 559: */ 560: public void paintDirtyRegions() 561: { 562: // Short cicuit if there is nothing to paint. 563: if (dirtyComponents.size() == 0) 564: return; 565: 566: // Swap dirtyRegions with dirtyRegionsWork to avoid locking. 567: synchronized (dirtyComponents) 568: { 569: HashMap swap = dirtyComponents; 570: dirtyComponents = dirtyComponentsWork; 571: dirtyComponentsWork = swap; 572: } 573: 574: ArrayList repaintOrder = new ArrayList(dirtyComponentsWork.size());; 575: // We sort the components by their size here. This way we have a good 576: // chance that painting the bigger components also paints the smaller 577: // components and we don't need to paint them twice. 578: repaintOrder.addAll(dirtyComponentsWork.keySet()); 579: 580: if (comparator == null) 581: comparator = new ComponentComparator(); 582: Collections.sort(repaintOrder, comparator); 583: repaintUnderway = true; 584: for (Iterator i = repaintOrder.iterator(); i.hasNext();) 585: { 586: JComponent comp = (JComponent) i.next(); 587: // If a component is marked completely clean in the meantime, then skip 588: // it. 589: Rectangle damaged = (Rectangle) dirtyComponentsWork.remove(comp); 590: if (damaged == null || damaged.isEmpty()) 591: continue; 592: comp.paintImmediately(damaged); 593: } 594: repaintUnderway = false; 595: commitRemainingBuffers(); 596: } 597: 598: /** 599: * Get an offscreen buffer for painting a component's image. This image 600: * may be smaller than the proposed dimensions, depending on the value of 601: * the {@link #doubleBufferMaximumSize} property. 602: * 603: * @param component The component to return an offscreen buffer for 604: * @param proposedWidth The proposed width of the offscreen buffer 605: * @param proposedHeight The proposed height of the offscreen buffer 606: * 607: * @return A shared offscreen buffer for painting 608: */ 609: public Image getOffscreenBuffer(Component component, int proposedWidth, 610: int proposedHeight) 611: { 612: Component root = getRoot(component); 613: Image buffer = (Image) offscreenBuffers.get(root); 614: if (buffer == null 615: || buffer.getWidth(null) < proposedWidth 616: || buffer.getHeight(null) < proposedHeight) 617: { 618: int width = Math.max(proposedWidth, root.getWidth()); 619: width = Math.min(doubleBufferMaximumSize.width, width); 620: int height = Math.max(proposedHeight, root.getHeight()); 621: height = Math.min(doubleBufferMaximumSize.height, height); 622: buffer = component.createImage(width, height); 623: offscreenBuffers.put(root, buffer); 624: } 625: return buffer; 626: } 627: 628: /** 629: * Gets the root of the component given. If a parent of the 630: * component is an instance of Applet, then the applet is 631: * returned. The applet is considered the root for painting. 632: * Otherwise, the root Window is returned if it exists. 633: * 634: * @param comp - The component to get the root for. 635: * @return the parent root. An applet if it is a parent, 636: * or the root window. If neither exist, null is returned. 637: */ 638: private Component getRoot(Component comp) 639: { 640: Applet app = null; 641: 642: while (comp != null) 643: { 644: if (app == null && comp instanceof Window) 645: return comp; 646: else if (comp instanceof Applet) 647: app = (Applet) comp; 648: comp = comp.getParent(); 649: } 650: 651: return app; 652: } 653: 654: /** 655: * Blits the back buffer of the specified root component to the screen. If 656: * the RepaintManager is currently working on a paint request, the commit 657: * requests are queued up and committed at once when the paint request is 658: * done (by {@link #commitRemainingBuffers}). This is package private because 659: * it must get called by JComponent. 660: * 661: * @param root the component, either a Window or an Applet instance 662: * @param area the area to paint on screen 663: */ 664: void commitBuffer(Component root, Rectangle area) 665: { 666: // We synchronize on dirtyComponents here because that is what 667: // paintDirtyRegions also synchronizes on while painting. 668: synchronized (dirtyComponents) 669: { 670: // If the RepaintManager is not currently painting, then directly 671: // blit the requested buffer on the screen. 672: if (! repaintUnderway) 673: { 674: Graphics g = root.getGraphics(); 675: Image buffer = (Image) offscreenBuffers.get(root); 676: Rectangle clip = g.getClipBounds(); 677: if (clip != null) 678: area = SwingUtilities.computeIntersection(clip.x, clip.y, 679: clip.width, clip.height, 680: area); 681: int dx1 = area.x; 682: int dy1 = area.y; 683: int dx2 = area.x + area.width; 684: int dy2 = area.y + area.height; 685: // Make sure we have a sane clip at this point. 686: g.clipRect(area.x, area.y, area.width, area.height); 687: 688: // Make sure the coordinates are inside the buffer, everything else 689: // might lead to problems. 690: // TODO: This code should not really be necessary, however, in fact 691: // we have two issues here: 692: // 1. We shouldn't get repaint requests in areas outside the buffer 693: // region in the first place. This still happens for example 694: // when a component is inside a JViewport, and the component has 695: // a size that would reach beyond the window size. 696: // 2. Graphics.drawImage() should not behave strange when trying 697: // to draw regions outside the image. 698: int bufferWidth = buffer.getWidth(root); 699: int bufferHeight = buffer.getHeight(root); 700: dx1 = Math.min(bufferWidth, dx1); 701: dy1 = Math.min(bufferHeight, dy1); 702: dx2 = Math.min(bufferWidth, dx2); 703: dy2 = Math.min(bufferHeight, dy2); 704: g.drawImage(buffer, 0, 0, root); 705: g.dispose(); 706: } 707: // Otherwise queue this request up, until all the RepaintManager work 708: // is done. 709: else 710: { 711: if (commitRequests.containsKey(root)) 712: SwingUtilities.computeUnion(area.x, area.y, area.width, 713: area.height, 714: (Rectangle) commitRequests.get(root)); 715: else 716: commitRequests.put(root, area); 717: } 718: } 719: } 720: 721: /** 722: * Commits the queued up back buffers to screen all at once. 723: */ 724: private void commitRemainingBuffers() 725: { 726: // We synchronize on dirtyComponents here because that is what 727: // paintDirtyRegions also synchronizes on while painting. 728: synchronized (dirtyComponents) 729: { 730: Set entrySet = commitRequests.entrySet(); 731: Iterator i = entrySet.iterator(); 732: while (i.hasNext()) 733: { 734: Map.Entry entry = (Map.Entry) i.next(); 735: Component root = (Component) entry.getKey(); 736: Rectangle area = (Rectangle) entry.getValue(); 737: commitBuffer(root, area); 738: i.remove(); 739: } 740: } 741: } 742: 743: /** 744: * Creates and returns a volatile offscreen buffer for the specified 745: * component that can be used as a double buffer. The returned image 746: * is a {@link VolatileImage}. Its size will be <code>(proposedWidth, 747: * proposedHeight)</code> except when the maximum double buffer size 748: * has been set in this RepaintManager. 749: * 750: * @param comp the Component for which to create a volatile buffer 751: * @param proposedWidth the proposed width of the buffer 752: * @param proposedHeight the proposed height of the buffer 753: * 754: * @since 1.4 755: * 756: * @see VolatileImage 757: */ 758: public Image getVolatileOffscreenBuffer(Component comp, int proposedWidth, 759: int proposedHeight) 760: { 761: int maxWidth = doubleBufferMaximumSize.width; 762: int maxHeight = doubleBufferMaximumSize.height; 763: return comp.createVolatileImage(Math.min(maxWidth, proposedWidth), 764: Math.min(maxHeight, proposedHeight)); 765: } 766: 767: 768: /** 769: * Get the value of the {@link #doubleBufferMaximumSize} property. 770: * 771: * @return The current value of the property 772: * 773: * @see #setDoubleBufferMaximumSize 774: */ 775: public Dimension getDoubleBufferMaximumSize() 776: { 777: return doubleBufferMaximumSize; 778: } 779: 780: /** 781: * Set the value of the {@link #doubleBufferMaximumSize} property. 782: * 783: * @param size The new value of the property 784: * 785: * @see #getDoubleBufferMaximumSize 786: */ 787: public void setDoubleBufferMaximumSize(Dimension size) 788: { 789: doubleBufferMaximumSize = size; 790: } 791: 792: /** 793: * Set the value of the {@link #doubleBufferingEnabled} property. 794: * 795: * @param buffer The new value of the property 796: * 797: * @see #isDoubleBufferingEnabled 798: */ 799: public void setDoubleBufferingEnabled(boolean buffer) 800: { 801: doubleBufferingEnabled = buffer; 802: } 803: 804: /** 805: * Get the value of the {@link #doubleBufferingEnabled} property. 806: * 807: * @return The current value of the property 808: * 809: * @see #setDoubleBufferingEnabled 810: */ 811: public boolean isDoubleBufferingEnabled() 812: { 813: return doubleBufferingEnabled; 814: } 815: 816: public String toString() 817: { 818: return "RepaintManager"; 819: } 820: }
GNU Classpath (0.91) |