GNU Classpath (0.19) | ||
Frames | No Frames |
1: /* JComponent.java -- Every component in swing inherits from this class. 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.AWTEvent; 43: import java.awt.Color; 44: import java.awt.Component; 45: import java.awt.Container; 46: import java.awt.Dimension; 47: import java.awt.EventQueue; 48: import java.awt.FlowLayout; 49: import java.awt.FocusTraversalPolicy; 50: import java.awt.Font; 51: import java.awt.Graphics; 52: import java.awt.Graphics2D; 53: import java.awt.Image; 54: import java.awt.Insets; 55: import java.awt.Point; 56: import java.awt.Rectangle; 57: import java.awt.Shape; 58: import java.awt.Window; 59: import java.awt.dnd.DropTarget; 60: import java.awt.event.ActionEvent; 61: import java.awt.event.ActionListener; 62: import java.awt.event.ContainerEvent; 63: import java.awt.event.ContainerListener; 64: import java.awt.event.FocusEvent; 65: import java.awt.event.FocusListener; 66: import java.awt.event.KeyEvent; 67: import java.awt.event.MouseEvent; 68: import java.awt.geom.Rectangle2D; 69: import java.awt.peer.LightweightPeer; 70: import java.beans.PropertyChangeEvent; 71: import java.beans.PropertyChangeListener; 72: import java.beans.PropertyVetoException; 73: import java.beans.VetoableChangeListener; 74: import java.io.Serializable; 75: import java.util.EventListener; 76: import java.util.Hashtable; 77: import java.util.Locale; 78: import java.util.Set; 79: 80: import javax.accessibility.Accessible; 81: import javax.accessibility.AccessibleContext; 82: import javax.accessibility.AccessibleExtendedComponent; 83: import javax.accessibility.AccessibleKeyBinding; 84: import javax.accessibility.AccessibleRole; 85: import javax.accessibility.AccessibleStateSet; 86: import javax.swing.border.Border; 87: import javax.swing.border.CompoundBorder; 88: import javax.swing.border.TitledBorder; 89: import javax.swing.event.AncestorEvent; 90: import javax.swing.event.AncestorListener; 91: import javax.swing.event.EventListenerList; 92: import javax.swing.event.SwingPropertyChangeSupport; 93: import javax.swing.plaf.ComponentUI; 94: 95: /** 96: * The base class of all Swing components. 97: * It contains generic methods to manage events, properties and sizes. Actual 98: * drawing of the component is channeled to a look-and-feel class that is 99: * implemented elsewhere. 100: * 101: * @author Ronald Veldema (rveldema&064;cs.vu.nl) 102: * @author Graydon Hoare (graydon&064;redhat.com) 103: */ 104: public abstract class JComponent extends Container implements Serializable 105: { 106: private static final long serialVersionUID = -7908749299918704233L; 107: 108: /** 109: * Accessibility support is currently missing. 110: */ 111: protected AccessibleContext accessibleContext; 112: 113: /** 114: * Basic accessibility support for <code>JComponent</code> derived 115: * widgets. 116: */ 117: public abstract class AccessibleJComponent 118: extends AccessibleAWTContainer 119: implements AccessibleExtendedComponent 120: { 121: /** 122: * Accessibility support for <code>JComponent</code>'s focus handler. 123: */ 124: protected class AccessibleFocusHandler 125: implements FocusListener 126: { 127: protected AccessibleFocusHandler() 128: { 129: // TODO: Implement this properly. 130: } 131: public void focusGained(FocusEvent event) 132: { 133: // TODO: Implement this properly. 134: } 135: public void focusLost(FocusEvent valevent) 136: { 137: // TODO: Implement this properly. 138: } 139: } 140: 141: /** 142: * Accessibility support for <code>JComponent</code>'s container handler. 143: */ 144: protected class AccessibleContainerHandler 145: implements ContainerListener 146: { 147: protected AccessibleContainerHandler() 148: { 149: // TODO: Implement this properly. 150: } 151: public void componentAdded(ContainerEvent event) 152: { 153: // TODO: Implement this properly. 154: } 155: public void componentRemoved(ContainerEvent valevent) 156: { 157: // TODO: Implement this properly. 158: } 159: } 160: 161: private static final long serialVersionUID = -7047089700479897799L; 162: 163: protected ContainerListener accessibleContainerHandler; 164: protected FocusListener accessibleFocusHandler; 165: 166: /** 167: * Manages the property change listeners; 168: */ 169: private SwingPropertyChangeSupport changeSupport; 170: 171: protected AccessibleJComponent() 172: { 173: changeSupport = new SwingPropertyChangeSupport(this); 174: } 175: 176: /** 177: * Adds a property change listener to the list of registered listeners. 178: * 179: * @param listener the listener to add 180: */ 181: public void addPropertyChangeListener(PropertyChangeListener listener) 182: { 183: changeSupport.addPropertyChangeListener(listener); 184: } 185: 186: /** 187: * Removes a propery change listener from the list of registered listeners. 188: * 189: * @param listener the listener to remove 190: */ 191: public void removePropertyChangeListener(PropertyChangeListener listener) 192: { 193: changeSupport.removePropertyChangeListener(listener); 194: } 195: 196: /** 197: * Returns the number of accessible children of this object. 198: * 199: * @return the number of accessible children of this object 200: */ 201: public int getAccessibleChildrenCount() 202: { 203: int count = 0; 204: Component[] children = getComponents(); 205: for (int i = 0; i < children.length; ++i) 206: { 207: if (children[i] instanceof Accessible) 208: count++; 209: } 210: return count; 211: } 212: 213: /** 214: * Returns the accessible child component at index <code>i</code>. 215: * 216: * @param i the index of the accessible child to return 217: * 218: * @return the accessible child component at index <code>i</code> 219: */ 220: public Accessible getAccessibleChild(int i) 221: { 222: int index = 0; 223: Component[] children = getComponents(); 224: Accessible found = null; 225: for (int j = 0; index != i; j++) 226: { 227: if (children[j] instanceof Accessible) 228: index++; 229: if (index == i) 230: found = (Accessible) children[index]; 231: } 232: // TODO: Figure out what to do when i is not a valid index. 233: return found; 234: } 235: 236: /** 237: * Returns the accessible state set of this component. 238: * 239: * @return the accessible state set of this component 240: */ 241: public AccessibleStateSet getAccessibleStateSet() 242: { 243: // FIXME: Figure out which states should be set here, and which are 244: // inherited from the super class. 245: return super.getAccessibleStateSet(); 246: } 247: 248: /** 249: * Returns the localized name for this object. Generally this should 250: * almost never return {@link Component#getName()} since that is not 251: * a localized name. If the object is some kind of text component (like 252: * a menu item), then the value of the object may be returned. Also, if 253: * the object has a tooltip, the value of the tooltip may also be 254: * appropriate. 255: * 256: * @return the localized name for this object or <code>null</code> if this 257: * object has no name 258: */ 259: public String getAccessibleName() 260: { 261: // TODO: Figure out what exactly to return here. It's possible that this 262: // method simply should return null. 263: return null; 264: } 265: 266: /** 267: * Returns the localized description of this object. 268: * 269: * @return the localized description of this object or <code>null</code> 270: * if this object has no description 271: */ 272: public String getAccessibleDescription() 273: { 274: // TODO: Figure out what exactly to return here. It's possible that this 275: // method simply should return null. 276: return null; 277: } 278: 279: /** 280: * Returns the accessible role of this component. 281: * 282: * @return the accessible role of this component 283: * 284: * @see AccessibleRole 285: */ 286: public AccessibleRole getAccessibleRole() 287: { 288: // TODO: Check if this is correct. 289: return AccessibleRole.SWING_COMPONENT; 290: } 291: 292: /** 293: * Recursivly searches a border hierarchy (starting at <code>border) for 294: * a titled border and returns the title if one is found, <code>null</code> 295: * otherwise. 296: * 297: * @param border the border to start search from 298: * 299: * @return the border title of a possibly found titled border 300: */ 301: protected String getBorderTitle(Border border) 302: { 303: String title = null; 304: if (border instanceof CompoundBorder) 305: { 306: CompoundBorder compound = (CompoundBorder) border; 307: Border inner = compound.getInsideBorder(); 308: title = getBorderTitle(inner); 309: if (title == null) 310: { 311: Border outer = compound.getOutsideBorder(); 312: title = getBorderTitle(outer); 313: } 314: } 315: else if (border instanceof TitledBorder) 316: { 317: TitledBorder titled = (TitledBorder) border; 318: title = titled.getTitle(); 319: } 320: return title; 321: } 322: 323: /** 324: * Returns the tooltip text for this accessible component. 325: * 326: * @return the tooltip text for this accessible component 327: */ 328: public String getToolTipText() 329: { 330: return JComponent.this.getToolTipText(); 331: } 332: 333: /** 334: * Returns the title of the border of this accessible component if 335: * this component has a titled border, otherwise returns <code>null</code>. 336: * 337: * @return the title of the border of this accessible component if 338: * this component has a titled border, otherwise returns 339: * <code>null</code> 340: */ 341: public String getTitledBorderText() 342: { 343: return getBorderTitle(getBorder()); 344: } 345: 346: /** 347: * Returns the keybindings associated with this accessible component or 348: * <code>null</code> if the component does not support key bindings. 349: * 350: * @return the keybindings associated with this accessible component 351: */ 352: public AccessibleKeyBinding getAccessibleKeyBinding() 353: { 354: // TODO: Implement this properly. 355: return null; 356: } 357: } 358: 359: /** 360: * An explicit value for the component's preferred size; if not set by a 361: * user, this is calculated on the fly by delegating to the {@link 362: * ComponentUI#getPreferredSize} method on the {@link #ui} property. 363: */ 364: Dimension preferredSize; 365: 366: /** 367: * An explicit value for the component's minimum size; if not set by a 368: * user, this is calculated on the fly by delegating to the {@link 369: * ComponentUI#getMinimumSize} method on the {@link #ui} property. 370: */ 371: Dimension minimumSize; 372: 373: /** 374: * An explicit value for the component's maximum size; if not set by a 375: * user, this is calculated on the fly by delegating to the {@link 376: * ComponentUI#getMaximumSize} method on the {@link #ui} property. 377: */ 378: Dimension maximumSize; 379: 380: /** 381: * A value between 0.0 and 1.0 indicating the preferred horizontal 382: * alignment of the component, relative to its siblings. The values 383: * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link 384: * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>, 385: * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout 386: * managers use this property. 387: * 388: * @see #getAlignmentX 389: * @see #setAlignmentX 390: * @see javax.swing.OverlayLayout 391: * @see javax.swing.BoxLayout 392: */ 393: float alignmentX = 0.5f; 394: 395: /** 396: * A value between 0.0 and 1.0 indicating the preferred vertical 397: * alignment of the component, relative to its siblings. The values 398: * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link 399: * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>, 400: * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout 401: * managers use this property. 402: * 403: * @see #getAlignmentY 404: * @see #setAlignmentY 405: * @see javax.swing.OverlayLayout 406: * @see javax.swing.BoxLayout 407: */ 408: float alignmentY = 0.5f; 409: 410: /** 411: * The border painted around this component. 412: * 413: * @see #paintBorder 414: */ 415: Border border; 416: 417: /** 418: * The text to show in the tooltip associated with this component. 419: * 420: * @see #setToolTipText 421: * @see #getToolTipText() 422: */ 423: String toolTipText; 424: 425: /** 426: * <p>Whether to double buffer this component when painting. This flag 427: * should generally be <code>true</code>, to ensure good painting 428: * performance.</p> 429: * 430: * <p>All children of a double buffered component are painted into the 431: * double buffer automatically, so only the top widget in a window needs 432: * to be double buffered.</p> 433: * 434: * @see #setDoubleBuffered 435: * @see #isDoubleBuffered 436: * @see #paint 437: */ 438: boolean doubleBuffered = true; 439: 440: /** 441: * A set of flags indicating which debugging graphics facilities should 442: * be enabled on this component. The values should be a combination of 443: * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION}, 444: * {@link DebugGraphics#FLASH_OPTION}, or {@link 445: * DebugGraphics#BUFFERED_OPTION}. 446: * 447: * @see #setDebugGraphicsOptions 448: * @see #getDebugGraphicsOptions 449: * @see DebugGraphics 450: * @see #getComponentGraphics 451: */ 452: int debugGraphicsOptions; 453: 454: /** 455: * <p>This property controls two independent behaviors simultaneously.</p> 456: * 457: * <p>First, it controls whether to fill the background of this widget 458: * when painting its body. This affects calls to {@link 459: * JComponent#paintComponent}, which in turn calls {@link 460: * ComponentUI#update} on the component's {@link #ui} property. If the 461: * component is opaque during this call, the background will be filled 462: * before calling {@link ComponentUI#paint}. This happens merely as a 463: * convenience; you may fill the component's background yourself too, 464: * but there is no need to do so if you will be filling with the same 465: * color.</p> 466: * 467: * <p>Second, it the opaque property informs swing's repaint system 468: * whether it will be necessary to paint the components "underneath" this 469: * component, in Z-order. If the component is opaque, it is considered to 470: * completely occlude components "underneath" it, so they will not be 471: * repainted along with the opaque component.</p> 472: * 473: * <p>The default value for this property is <code>false</code>, but most 474: * components will want to set it to <code>true</code> when installing UI 475: * defaults in {@link ComponentUI#installUI}.</p> 476: * 477: * @see #setOpaque 478: * @see #isOpaque 479: * @see #paintComponent 480: */ 481: boolean opaque = false; 482: 483: /** 484: * The user interface delegate for this component. Event delivery and 485: * repainting of the component are usually delegated to this object. 486: * 487: * @see #setUI 488: * @see #getUIClassID 489: * @see #updateUI 490: */ 491: protected ComponentUI ui; 492: 493: /** 494: * A hint to the focus system that this component should or should not 495: * get focus. If this is <code>false</code>, swing will not try to 496: * request focus on this component; if <code>true</code>, swing might 497: * try to request focus, but the request might fail. Thus it is only 498: * a hint guiding swing's behavior. 499: * 500: * @see #requestFocus() 501: * @see #isRequestFocusEnabled 502: * @see #setRequestFocusEnabled 503: */ 504: boolean requestFocusEnabled; 505: 506: /** 507: * Flag indicating behavior of this component when the mouse is dragged 508: * outside the component and the mouse <em>stops moving</em>. If 509: * <code>true</code>, synthetic mouse events will be delivered on regular 510: * timed intervals, continuing off in the direction the mouse exited the 511: * component, until the mouse is released or re-enters the component. 512: * 513: * @see #setAutoscrolls 514: * @see #getAutoscrolls 515: */ 516: boolean autoscrolls = false; 517: 518: /** 519: * Indicates whether the current paint call is already double buffered or 520: * not. 521: */ 522: static boolean isPaintingDoubleBuffered = false; 523: 524: /** 525: * Listeners for events other than {@link PropertyChangeEvent} are 526: * handled by this listener list. PropertyChangeEvents are handled in 527: * {@link #changeSupport}. 528: */ 529: protected EventListenerList listenerList = new EventListenerList(); 530: 531: /** 532: * Support for {@link PropertyChangeEvent} events. This is constructed 533: * lazily when the component gets its first {@link 534: * PropertyChangeListener} subscription; until then it's an empty slot. 535: */ 536: private SwingPropertyChangeSupport changeSupport; 537: 538: 539: /** 540: * Storage for "client properties", which are key/value pairs associated 541: * with this component by a "client", such as a user application or a 542: * layout manager. This is lazily constructed when the component gets its 543: * first client property. 544: */ 545: private Hashtable clientProperties; 546: 547: private InputMap inputMap_whenFocused; 548: private InputMap inputMap_whenAncestorOfFocused; 549: private InputMap inputMap_whenInFocusedWindow; 550: private ActionMap actionMap; 551: /** @since 1.3 */ 552: private boolean verifyInputWhenFocusTarget; 553: private InputVerifier inputVerifier; 554: 555: private TransferHandler transferHandler; 556: 557: /** 558: * A cached Rectangle object to be reused. Be careful when you use that, 559: * so that it doesn't get modified in another context within the same 560: * method call chain. 561: */ 562: private static transient Rectangle rectCache; 563: 564: /** 565: * The default locale of the component. 566: * 567: * @see #getDefaultLocale 568: * @see #setDefaultLocale 569: */ 570: private static Locale defaultLocale; 571: 572: public static final String TOOL_TIP_TEXT_KEY = "ToolTipText"; 573: 574: /** 575: * Constant used to indicate that no condition has been assigned to a 576: * particular action. 577: * 578: * @see #registerKeyboardAction(ActionListener, KeyStroke, int) 579: */ 580: public static final int UNDEFINED_CONDITION = -1; 581: 582: /** 583: * Constant used to indicate that an action should be performed only when 584: * the component has focus. 585: * 586: * @see #registerKeyboardAction(ActionListener, KeyStroke, int) 587: */ 588: public static final int WHEN_FOCUSED = 0; 589: 590: /** 591: * Constant used to indicate that an action should be performed only when 592: * the component is an ancestor of the component which has focus. 593: * 594: * @see #registerKeyboardAction(ActionListener, KeyStroke, int) 595: */ 596: public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1; 597: 598: /** 599: * Constant used to indicate that an action should be performed only when 600: * the component is in the window which has focus. 601: * 602: * @see #registerKeyboardAction(ActionListener, KeyStroke, int) 603: */ 604: public static final int WHEN_IN_FOCUSED_WINDOW = 2; 605: 606: /** 607: * Indicates if this component is completely dirty or not. This is used 608: * by the RepaintManager's 609: * {@link RepaintManager#isCompletelyDirty(JComponent)} method. 610: */ 611: boolean isCompletelyDirty = false; 612: 613: /** 614: * Creates a new <code>JComponent</code> instance. 615: */ 616: public JComponent() 617: { 618: super(); 619: super.setLayout(new FlowLayout()); 620: setDropTarget(new DropTarget()); 621: defaultLocale = Locale.getDefault(); 622: debugGraphicsOptions = DebugGraphics.NONE_OPTION; 623: setRequestFocusEnabled(true); 624: } 625: 626: /** 627: * Helper to lazily construct and return the client properties table. 628: * 629: * @return The current client properties table 630: * 631: * @see #clientProperties 632: * @see #getClientProperty 633: * @see #putClientProperty 634: */ 635: private Hashtable getClientProperties() 636: { 637: if (clientProperties == null) 638: clientProperties = new Hashtable(); 639: return clientProperties; 640: } 641: 642: /** 643: * Get a client property associated with this component and a particular 644: * key. 645: * 646: * @param key The key with which to look up the client property 647: * 648: * @return A client property associated with this object and key 649: * 650: * @see #clientProperties 651: * @see #getClientProperties 652: * @see #putClientProperty 653: */ 654: public final Object getClientProperty(Object key) 655: { 656: return getClientProperties().get(key); 657: } 658: 659: /** 660: * Add a client property <code>value</code> to this component, associated 661: * with <code>key</code>. If there is an existing client property 662: * associated with <code>key</code>, it will be replaced. A 663: * {@link PropertyChangeEvent} is sent to registered listeners (with the 664: * name of the property being <code>key.toString()</code>). 665: * 666: * @param key The key of the client property association to add 667: * @param value The value of the client property association to add 668: * 669: * @see #clientProperties 670: * @see #getClientProperties 671: * @see #getClientProperty 672: */ 673: public final void putClientProperty(Object key, Object value) 674: { 675: Hashtable t = getClientProperties(); 676: Object old = t.get(key); 677: if (value != null) 678: t.put(key, value); 679: else 680: t.remove(key); 681: firePropertyChange(key.toString(), old, value); 682: } 683: 684: /** 685: * Unregister an <code>AncestorListener</code>. 686: * 687: * @param listener The listener to unregister 688: * 689: * @see #addAncestorListener 690: */ 691: public void removeAncestorListener(AncestorListener listener) 692: { 693: listenerList.remove(AncestorListener.class, listener); 694: } 695: 696: /** 697: * Unregister a <code>PropertyChangeListener</code>. 698: * 699: * @param listener The listener to register 700: * 701: * @see #addPropertyChangeListener(PropertyChangeListener) 702: * @see #changeSupport 703: */ 704: public void removePropertyChangeListener(PropertyChangeListener listener) 705: { 706: if (changeSupport != null) 707: changeSupport.removePropertyChangeListener(listener); 708: } 709: 710: /** 711: * Unregister a <code>PropertyChangeListener</code>. 712: * 713: * @param propertyName The property name to unregister the listener from 714: * @param listener The listener to unregister 715: * 716: * @see #addPropertyChangeListener(String, PropertyChangeListener) 717: * @see #changeSupport 718: */ 719: public void removePropertyChangeListener(String propertyName, 720: PropertyChangeListener listener) 721: { 722: if (changeSupport != null) 723: changeSupport.removePropertyChangeListener(propertyName, listener); 724: } 725: 726: /** 727: * Unregister a <code>VetoableChangeChangeListener</code>. 728: * 729: * @param listener The listener to unregister 730: * 731: * @see #addVetoableChangeListener 732: */ 733: public void removeVetoableChangeListener(VetoableChangeListener listener) 734: { 735: listenerList.remove(VetoableChangeListener.class, listener); 736: } 737: 738: /** 739: * Register an <code>AncestorListener</code>. 740: * 741: * @param listener The listener to register 742: * 743: * @see #removeVetoableChangeListener 744: */ 745: public void addAncestorListener(AncestorListener listener) 746: { 747: listenerList.add(AncestorListener.class, listener); 748: } 749: 750: /** 751: * Register a <code>PropertyChangeListener</code>. This listener will 752: * receive any PropertyChangeEvent, regardless of property name. To 753: * listen to a specific property name, use {@link 754: * #addPropertyChangeListener(String,PropertyChangeListener)} instead. 755: * 756: * @param listener The listener to register 757: * 758: * @see #removePropertyChangeListener(PropertyChangeListener) 759: * @see #changeSupport 760: */ 761: public void addPropertyChangeListener(PropertyChangeListener listener) 762: { 763: if (changeSupport == null) 764: changeSupport = new SwingPropertyChangeSupport(this); 765: changeSupport.addPropertyChangeListener(listener); 766: } 767: 768: /** 769: * Register a <code>PropertyChangeListener</code> for a specific, named 770: * property. To listen to all property changes, regardless of name, use 771: * {@link #addPropertyChangeListener(PropertyChangeListener)} instead. 772: * 773: * @param propertyName The property name to listen to 774: * @param listener The listener to register 775: * 776: * @see #removePropertyChangeListener(String, PropertyChangeListener) 777: * @see #changeSupport 778: */ 779: public void addPropertyChangeListener(String propertyName, 780: PropertyChangeListener listener) 781: { 782: listenerList.add(PropertyChangeListener.class, listener); 783: } 784: 785: /** 786: * Register a <code>VetoableChangeListener</code>. 787: * 788: * @param listener The listener to register 789: * 790: * @see #removeVetoableChangeListener 791: * @see #listenerList 792: */ 793: public void addVetoableChangeListener(VetoableChangeListener listener) 794: { 795: listenerList.add(VetoableChangeListener.class, listener); 796: } 797: 798: /** 799: * Return all registered listeners of a particular type. 800: * 801: * @param listenerType The type of listener to return 802: * 803: * @return All listeners in the {@link #listenerList} which 804: * are of the specified type 805: * 806: * @see #listenerList 807: */ 808: public EventListener[] getListeners(Class listenerType) 809: { 810: return listenerList.getListeners(listenerType); 811: } 812: 813: /** 814: * Return all registered <code>AncestorListener</code> objects. 815: * 816: * @return The set of <code>AncestorListener</code> objects in {@link 817: * #listenerList} 818: */ 819: public AncestorListener[] getAncestorListeners() 820: { 821: return (AncestorListener[]) getListeners(AncestorListener.class); 822: } 823: 824: /** 825: * Return all registered <code>VetoableChangeListener</code> objects. 826: * 827: * @return The set of <code>VetoableChangeListener</code> objects in {@link 828: * #listenerList} 829: */ 830: public VetoableChangeListener[] getVetoableChangeListeners() 831: { 832: return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class); 833: } 834: 835: /** 836: * Return all <code>PropertyChangeListener</code> objects registered to listen 837: * for a particular property. 838: * 839: * @param property The property to return the listeners of 840: * 841: * @return The set of <code>PropertyChangeListener</code> objects in 842: * {@link #changeSupport} registered to listen on the specified property 843: */ 844: public PropertyChangeListener[] getPropertyChangeListeners(String property) 845: { 846: return changeSupport == null ? new PropertyChangeListener[0] 847: : changeSupport.getPropertyChangeListeners(property); 848: } 849: 850: /** 851: * A variant of {@link #firePropertyChange(String,Object,Object)} 852: * for properties with <code>boolean</code> values. 853: */ 854: public void firePropertyChange(String propertyName, boolean oldValue, 855: boolean newValue) 856: { 857: if (changeSupport != null) 858: changeSupport.firePropertyChange(propertyName, Boolean.valueOf(oldValue), 859: Boolean.valueOf(newValue)); 860: } 861: 862: /** 863: * A variant of {@link #firePropertyChange(String,Object,Object)} 864: * for properties with <code>byte</code> values. 865: */ 866: public void firePropertyChange(String propertyName, byte oldValue, 867: byte newValue) 868: { 869: if (changeSupport != null) 870: changeSupport.firePropertyChange(propertyName, new Byte(oldValue), 871: new Byte(newValue)); 872: } 873: 874: /** 875: * A variant of {@link #firePropertyChange(String,Object,Object)} 876: * for properties with <code>char</code> values. 877: */ 878: public void firePropertyChange(String propertyName, char oldValue, 879: char newValue) 880: { 881: if (changeSupport != null) 882: changeSupport.firePropertyChange(propertyName, new Character(oldValue), 883: new Character(newValue)); 884: } 885: 886: /** 887: * A variant of {@link #firePropertyChange(String,Object,Object)} 888: * for properties with <code>double</code> values. 889: */ 890: public void firePropertyChange(String propertyName, double oldValue, 891: double newValue) 892: { 893: if (changeSupport != null) 894: changeSupport.firePropertyChange(propertyName, new Double(oldValue), 895: new Double(newValue)); 896: } 897: 898: /** 899: * A variant of {@link #firePropertyChange(String,Object,Object)} 900: * for properties with <code>float</code> values. 901: */ 902: public void firePropertyChange(String propertyName, float oldValue, 903: float newValue) 904: { 905: if (changeSupport != null) 906: changeSupport.firePropertyChange(propertyName, new Float(oldValue), 907: new Float(newValue)); 908: } 909: 910: /** 911: * A variant of {@link #firePropertyChange(String,Object,Object)} 912: * for properties with <code>int</code> values. 913: */ 914: public void firePropertyChange(String propertyName, int oldValue, 915: int newValue) 916: { 917: if (changeSupport != null) 918: changeSupport.firePropertyChange(propertyName, new Integer(oldValue), 919: new Integer(newValue)); 920: } 921: 922: /** 923: * A variant of {@link #firePropertyChange(String,Object,Object)} 924: * for properties with <code>long</code> values. 925: */ 926: public void firePropertyChange(String propertyName, long oldValue, 927: long newValue) 928: { 929: if (changeSupport != null) 930: changeSupport.firePropertyChange(propertyName, new Long(oldValue), 931: new Long(newValue)); 932: } 933: 934: /** 935: * Call {@link PropertyChangeListener#propertyChange} on all listeners 936: * registered to listen to a given property. Any method which changes 937: * the specified property of this component should call this method. 938: * 939: * @param propertyName The property which changed 940: * @param oldValue The old value of the property 941: * @param newValue The new value of the property 942: * 943: * @see #changeSupport 944: * @see #addPropertyChangeListener(PropertyChangeListener) 945: * @see #removePropertyChangeListener(PropertyChangeListener) 946: */ 947: protected void firePropertyChange(String propertyName, Object oldValue, 948: Object newValue) 949: { 950: if (changeSupport != null) 951: changeSupport.firePropertyChange(propertyName, oldValue, newValue); 952: } 953: 954: /** 955: * A variant of {@link #firePropertyChange(String,Object,Object)} 956: * for properties with <code>short</code> values. 957: */ 958: public void firePropertyChange(String propertyName, short oldValue, 959: short newValue) 960: { 961: if (changeSupport != null) 962: changeSupport.firePropertyChange(propertyName, new Short(oldValue), 963: new Short(newValue)); 964: } 965: 966: /** 967: * Call {@link VetoableChangeListener#vetoableChange} on all listeners 968: * registered to listen to a given property. Any method which changes 969: * the specified property of this component should call this method. 970: * 971: * @param propertyName The property which changed 972: * @param oldValue The old value of the property 973: * @param newValue The new value of the property 974: * 975: * @throws PropertyVetoException if the change was vetoed by a listener 976: * 977: * @see #addVetoableChangeListener 978: * @see #removeVetoableChangeListener 979: */ 980: protected void fireVetoableChange(String propertyName, Object oldValue, 981: Object newValue) 982: throws PropertyVetoException 983: { 984: VetoableChangeListener[] listeners = getVetoableChangeListeners(); 985: 986: PropertyChangeEvent evt = new PropertyChangeEvent(this, propertyName, oldValue, newValue); 987: 988: for (int i = 0; i < listeners.length; i++) 989: listeners[i].vetoableChange(evt); 990: } 991: 992: /** 993: * Get the value of the accessibleContext property for this component. 994: * 995: * @return the current value of the property 996: */ 997: public AccessibleContext getAccessibleContext() 998: { 999: return null; 1000: } 1001: 1002: /** 1003: * Get the value of the {@link #alignmentX} property. 1004: * 1005: * @return The current value of the property. 1006: * 1007: * @see #setAlignmentX 1008: * @see #alignmentY 1009: */ 1010: public float getAlignmentX() 1011: { 1012: return alignmentX; 1013: } 1014: 1015: /** 1016: * Get the value of the {@link #alignmentY} property. 1017: * 1018: * @return The current value of the property. 1019: * 1020: * @see #setAlignmentY 1021: * @see #alignmentX 1022: */ 1023: public float getAlignmentY() 1024: { 1025: return alignmentY; 1026: } 1027: 1028: /** 1029: * Get the current value of the {@link #autoscrolls} property. 1030: * 1031: * @return The current value of the property 1032: */ 1033: public boolean getAutoscrolls() 1034: { 1035: return autoscrolls; 1036: } 1037: 1038: /** 1039: * Set the value of the {@link #border} property. 1040: * 1041: * @param newBorder The new value of the property 1042: * 1043: * @see #getBorder 1044: */ 1045: public void setBorder(Border newBorder) 1046: { 1047: Border oldBorder = getBorder(); 1048: if (oldBorder == newBorder) 1049: return; 1050: 1051: border = newBorder; 1052: firePropertyChange("border", oldBorder, newBorder); 1053: repaint(); 1054: } 1055: 1056: /** 1057: * Get the value of the {@link #border} property. 1058: * 1059: * @return The property's current value 1060: * 1061: * @see #setBorder 1062: */ 1063: public Border getBorder() 1064: { 1065: return border; 1066: } 1067: 1068: /** 1069: * Get the component's current bounding box. If a rectangle is provided, 1070: * use this as the return value (adjusting its fields in place); 1071: * otherwise (of <code>null</code> is provided) return a new {@link 1072: * Rectangle}. 1073: * 1074: * @param rv Optional return value to use 1075: * 1076: * @return A rectangle bounding the component 1077: */ 1078: public Rectangle getBounds(Rectangle rv) 1079: { 1080: if (rv == null) 1081: return new Rectangle(getX(), getY(), getWidth(), getHeight()); 1082: else 1083: { 1084: rv.setBounds(getX(), getY(), getWidth(), getHeight()); 1085: return rv; 1086: } 1087: } 1088: 1089: /** 1090: * Prepares a graphics context for painting this object. If {@link 1091: * #debugGraphicsOptions} is not equal to {@link 1092: * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object 1093: * wrapping the parameter. Otherwise configure the parameter with this 1094: * component's foreground color and font. 1095: * 1096: * @param g The graphics context to wrap or configure 1097: * 1098: * @return A graphics context to paint this object with 1099: * 1100: * @see #debugGraphicsOptions 1101: * @see #paint 1102: */ 1103: protected Graphics getComponentGraphics(Graphics g) 1104: { 1105: Graphics g2 = g; 1106: int options = getDebugGraphicsOptions(); 1107: if (options != DebugGraphics.NONE_OPTION) 1108: { 1109: if (!(g2 instanceof DebugGraphics)) 1110: g2 = new DebugGraphics(g); 1111: DebugGraphics dg = (DebugGraphics) g2; 1112: dg.setDebugOptions(dg.getDebugOptions() | options); 1113: } 1114: g2.setFont(this.getFont()); 1115: g2.setColor(this.getForeground()); 1116: return g2; 1117: } 1118: 1119: /** 1120: * Get the value of the {@link #debugGraphicsOptions} property. 1121: * 1122: * @return The current value of the property. 1123: * 1124: * @see #setDebugGraphicsOptions 1125: * @see #debugGraphicsOptions 1126: */ 1127: public int getDebugGraphicsOptions() 1128: { 1129: String option = System.getProperty("gnu.javax.swing.DebugGraphics"); 1130: int options = debugGraphicsOptions; 1131: if (option != null && option.length() != 0) 1132: { 1133: if (options < 0) 1134: options = 0; 1135: 1136: if (option.equals("LOG")) 1137: options |= DebugGraphics.LOG_OPTION; 1138: else if (option.equals("FLASH")) 1139: options |= DebugGraphics.FLASH_OPTION; 1140: } 1141: return options; 1142: } 1143: 1144: /** 1145: * Get the component's insets, which are calculated from 1146: * the {@link #border} property. If the border is <code>null</code>, 1147: * calls {@link Container#getInsets}. 1148: * 1149: * @return The component's current insets 1150: */ 1151: public Insets getInsets() 1152: { 1153: if (border == null) 1154: return super.getInsets(); 1155: return getBorder().getBorderInsets(this); 1156: } 1157: 1158: /** 1159: * Get the component's insets, which are calculated from the {@link 1160: * #border} property. If the border is <code>null</code>, calls {@link 1161: * Container#getInsets}. The passed-in {@link Insets} value will be 1162: * used as the return value, if possible. 1163: * 1164: * @param insets Return value object to reuse, if possible 1165: * 1166: * @return The component's current insets 1167: */ 1168: public Insets getInsets(Insets insets) 1169: { 1170: Insets t = getInsets(); 1171: 1172: if (insets == null) 1173: return t; 1174: 1175: insets.left = t.left; 1176: insets.right = t.right; 1177: insets.top = t.top; 1178: insets.bottom = t.bottom; 1179: return insets; 1180: } 1181: 1182: /** 1183: * Get the component's location. The passed-in {@link Point} value 1184: * will be used as the return value, if possible. 1185: * 1186: * @param rv Return value object to reuse, if possible 1187: * 1188: * @return The component's current location 1189: */ 1190: public Point getLocation(Point rv) 1191: { 1192: if (rv == null) 1193: return new Point(getX(), getY()); 1194: 1195: rv.setLocation(getX(), getY()); 1196: return rv; 1197: } 1198: 1199: /** 1200: * Get the component's maximum size. If the {@link #maximumSize} property 1201: * has been explicitly set, it is returned. If the {@link #maximumSize} 1202: * property has not been set but the {@link #ui} property has been, the 1203: * result of {@link ComponentUI#getMaximumSize} is returned. If neither 1204: * property has been set, the result of {@link Container#getMaximumSize} 1205: * is returned. 1206: * 1207: * @return The maximum size of the component 1208: * 1209: * @see #maximumSize 1210: * @see #setMaximumSize 1211: */ 1212: public Dimension getMaximumSize() 1213: { 1214: if (maximumSize != null) 1215: return maximumSize; 1216: 1217: if (ui != null) 1218: { 1219: Dimension s = ui.getMaximumSize(this); 1220: if (s != null) 1221: return s; 1222: } 1223: 1224: Dimension p = super.getMaximumSize(); 1225: return p; 1226: } 1227: 1228: /** 1229: * Get the component's minimum size. If the {@link #minimumSize} property 1230: * has been explicitly set, it is returned. If the {@link #minimumSize} 1231: * property has not been set but the {@link #ui} property has been, the 1232: * result of {@link ComponentUI#getMinimumSize} is returned. If neither 1233: * property has been set, the result of {@link Container#getMinimumSize} 1234: * is returned. 1235: * 1236: * @return The minimum size of the component 1237: * 1238: * @see #minimumSize 1239: * @see #setMinimumSize 1240: */ 1241: public Dimension getMinimumSize() 1242: { 1243: if (minimumSize != null) 1244: return minimumSize; 1245: 1246: if (ui != null) 1247: { 1248: Dimension s = ui.getMinimumSize(this); 1249: if (s != null) 1250: return s; 1251: } 1252: 1253: Dimension p = super.getMinimumSize(); 1254: return p; 1255: } 1256: 1257: /** 1258: * Get the component's preferred size. If the {@link #preferredSize} 1259: * property has been explicitly set, it is returned. If the {@link 1260: * #preferredSize} property has not been set but the {@link #ui} property 1261: * has been, the result of {@link ComponentUI#getPreferredSize} is 1262: * returned. If neither property has been set, the result of {@link 1263: * Container#getPreferredSize} is returned. 1264: * 1265: * @return The preferred size of the component 1266: * 1267: * @see #preferredSize 1268: * @see #setPreferredSize 1269: */ 1270: public Dimension getPreferredSize() 1271: { 1272: Dimension prefSize = null; 1273: if (preferredSize != null) 1274: prefSize = preferredSize; 1275: 1276: else if (ui != null) 1277: { 1278: Dimension s = ui.getPreferredSize(this); 1279: if (s != null) 1280: prefSize = s; 1281: } 1282: 1283: if (prefSize == null) 1284: prefSize = super.getPreferredSize(); 1285: // make sure that prefSize is not smaller than minSize 1286: if (minimumSize != null && prefSize != null 1287: && (minimumSize.width > prefSize.width 1288: || minimumSize.height > prefSize.height)) 1289: prefSize = new Dimension(Math.max(minimumSize.width, prefSize.width), 1290: Math.max(minimumSize.height, prefSize.height)); 1291: return prefSize; 1292: } 1293: 1294: /** 1295: * Checks if a maximum size was explicitely set on the component. 1296: * 1297: * @return <code>true</code> if a maximum size was set, 1298: * <code>false</code> otherwise 1299: * 1300: * @since 1.3 1301: */ 1302: public boolean isMaximumSizeSet() 1303: { 1304: return maximumSize != null; 1305: } 1306: 1307: /** 1308: * Checks if a minimum size was explicitely set on the component. 1309: * 1310: * @return <code>true</code> if a minimum size was set, 1311: * <code>false</code> otherwise 1312: * 1313: * @since 1.3 1314: */ 1315: public boolean isMinimumSizeSet() 1316: { 1317: return minimumSize != null; 1318: } 1319: 1320: /** 1321: * Checks if a preferred size was explicitely set on the component. 1322: * 1323: * @return <code>true</code> if a preferred size was set, 1324: * <code>false</code> otherwise 1325: * 1326: * @since 1.3 1327: */ 1328: public boolean isPreferredSizeSet() 1329: { 1330: return preferredSize != null; 1331: } 1332: 1333: /** 1334: * Return the value of the <code>nextFocusableComponent</code> property. 1335: * 1336: * @return The current value of the property, or <code>null</code> 1337: * if none has been set. 1338: * 1339: * @deprecated See {@link java.awt.FocusTraversalPolicy} 1340: */ 1341: public Component getNextFocusableComponent() 1342: { 1343: return null; 1344: } 1345: 1346: /** 1347: * Return the set of {@link KeyStroke} objects which are registered 1348: * to initiate actions on this component. 1349: * 1350: * @return An array of the registered keystrokes 1351: */ 1352: public KeyStroke[] getRegisteredKeyStrokes() 1353: { 1354: return null; 1355: } 1356: 1357: /** 1358: * Returns the first ancestor of this component which is a {@link JRootPane}. 1359: * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>. 1360: * 1361: * @return An ancestral JRootPane, or <code>null</code> if none exists. 1362: */ 1363: public JRootPane getRootPane() 1364: { 1365: JRootPane p = SwingUtilities.getRootPane(this); 1366: return p; 1367: } 1368: 1369: /** 1370: * Get the component's size. The passed-in {@link Dimension} value 1371: * will be used as the return value, if possible. 1372: * 1373: * @param rv Return value object to reuse, if possible 1374: * 1375: * @return The component's current size 1376: */ 1377: public Dimension getSize(Dimension rv) 1378: { 1379: if (rv == null) 1380: return new Dimension(getWidth(), getHeight()); 1381: else 1382: { 1383: rv.setSize(getWidth(), getHeight()); 1384: return rv; 1385: } 1386: } 1387: 1388: /** 1389: * Return the <code>toolTip</code> property of this component, creating it and 1390: * setting it if it is currently <code>null</code>. This method can be 1391: * overridden in subclasses which wish to control the exact form of 1392: * tooltip created. 1393: * 1394: * @return The current toolTip 1395: */ 1396: public JToolTip createToolTip() 1397: { 1398: JToolTip toolTip = new JToolTip(); 1399: toolTip.setComponent(this); 1400: toolTip.setTipText(toolTipText); 1401: 1402: return toolTip; 1403: } 1404: 1405: /** 1406: * Return the location at which the {@link #toolTipText} property should be 1407: * displayed, when triggered by a particular mouse event. 1408: * 1409: * @param event The event the tooltip is being presented in response to 1410: * 1411: * @return The point at which to display a tooltip, or <code>null</code> 1412: * if swing is to choose a default location. 1413: */ 1414: public Point getToolTipLocation(MouseEvent event) 1415: { 1416: return null; 1417: } 1418: 1419: /** 1420: * Set the value of the {@link #toolTipText} property. 1421: * 1422: * @param text The new property value 1423: * 1424: * @see #getToolTipText() 1425: */ 1426: public void setToolTipText(String text) 1427: { 1428: if (text == null) 1429: { 1430: ToolTipManager.sharedInstance().unregisterComponent(this); 1431: toolTipText = null; 1432: return; 1433: } 1434: 1435: // XXX: The tip text doesn't get updated unless you set it to null 1436: // and then to something not-null. This is consistent with the behaviour 1437: // of Sun's ToolTipManager. 1438: 1439: String oldText = toolTipText; 1440: toolTipText = text; 1441: 1442: if (oldText == null) 1443: ToolTipManager.sharedInstance().registerComponent(this); 1444: } 1445: 1446: /** 1447: * Get the value of the {@link #toolTipText} property. 1448: * 1449: * @return The current property value 1450: * 1451: * @see #setToolTipText 1452: */ 1453: public String getToolTipText() 1454: { 1455: return toolTipText; 1456: } 1457: 1458: /** 1459: * Get the value of the {@link #toolTipText} property, in response to a 1460: * particular mouse event. 1461: * 1462: * @param event The mouse event which triggered the tooltip 1463: * 1464: * @return The current property value 1465: * 1466: * @see #setToolTipText 1467: */ 1468: public String getToolTipText(MouseEvent event) 1469: { 1470: return getToolTipText(); 1471: } 1472: 1473: /** 1474: * Return the top level ancestral container (usually a {@link 1475: * java.awt.Window} or {@link java.applet.Applet}) which this component is 1476: * contained within, or <code>null</code> if no ancestors exist. 1477: * 1478: * @return The top level container, if it exists 1479: */ 1480: public Container getTopLevelAncestor() 1481: { 1482: Container c = getParent(); 1483: for (Container peek = c; peek != null; peek = peek.getParent()) 1484: c = peek; 1485: return c; 1486: } 1487: 1488: /** 1489: * Compute the component's visible rectangle, which is defined 1490: * recursively as either the component's bounds, if it has no parent, or 1491: * the intersection of the component's bounds with the visible rectangle 1492: * of its parent. 1493: * 1494: * @param rect The return value slot to place the visible rectangle in 1495: */ 1496: public void computeVisibleRect(Rectangle rect) 1497: { 1498: Component c = getParent(); 1499: if (c != null && c instanceof JComponent) 1500: { 1501: ((JComponent) c).computeVisibleRect(rect); 1502: rect.translate(-getX(), -getY()); 1503: Rectangle2D.intersect(rect, 1504: new Rectangle(0, 0, getWidth(), getHeight()), 1505: rect); 1506: } 1507: else 1508: rect.setRect(0, 0, getWidth(), getHeight()); 1509: } 1510: 1511: /** 1512: * Return the component's visible rectangle in a new {@link Rectangle}, 1513: * rather than via a return slot. 1514: * 1515: * @return The component's visible rectangle 1516: * 1517: * @see #computeVisibleRect(Rectangle) 1518: */ 1519: public Rectangle getVisibleRect() 1520: { 1521: Rectangle r = new Rectangle(); 1522: computeVisibleRect(r); 1523: return r; 1524: } 1525: 1526: /** 1527: * <p>Requests that this component receive input focus, giving window 1528: * focus to the top level ancestor of this component. Only works on 1529: * displayable, focusable, visible components.</p> 1530: * 1531: * <p>This method should not be called by clients; it is intended for 1532: * focus implementations. Use {@link Component#requestFocus()} instead.</p> 1533: * 1534: * @see Component#requestFocus() 1535: */ 1536: public void grabFocus() 1537: { 1538: // TODO: Implement this properly. 1539: } 1540: 1541: /** 1542: * Get the value of the {@link #doubleBuffered} property. 1543: * 1544: * @return The property's current value 1545: */ 1546: public boolean isDoubleBuffered() 1547: { 1548: return doubleBuffered; 1549: } 1550: 1551: /** 1552: * Return <code>true</code> if the provided component has no native peer; 1553: * in other words, if it is a "lightweight component". 1554: * 1555: * @param c The component to test for lightweight-ness 1556: * 1557: * @return Whether or not the component is lightweight 1558: */ 1559: public static boolean isLightweightComponent(Component c) 1560: { 1561: return c.getPeer() instanceof LightweightPeer; 1562: } 1563: 1564: /** 1565: * Return <code>true</code> if you wish this component to manage its own 1566: * focus. In particular: if you want this component to be sent 1567: * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not 1568: * have its children considered as focus transfer targets. If 1569: * <code>true</code>, focus traversal around this component changes to 1570: * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>. 1571: * 1572: * @return <code>true</code> if you want this component to manage its own 1573: * focus, otherwise (by default) <code>false</code> 1574: * 1575: * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and 1576: * {@link Container#setFocusCycleRoot(boolean)} instead 1577: */ 1578: public boolean isManagingFocus() 1579: { 1580: return false; 1581: } 1582: 1583: /** 1584: * Return the current value of the {@link #opaque} property. 1585: * 1586: * @return The current property value 1587: */ 1588: public boolean isOpaque() 1589: { 1590: return opaque; 1591: } 1592: 1593: /** 1594: * Return <code>true</code> if the component can guarantee that none of its 1595: * children will overlap in Z-order. This is a hint to the painting system. 1596: * The default is to return <code>true</code>, but some components such as 1597: * {@link JLayeredPane} should override this to return <code>false</code>. 1598: * 1599: * @return Whether the component tiles its children 1600: */ 1601: public boolean isOptimizedDrawingEnabled() 1602: { 1603: return true; 1604: } 1605: 1606: /** 1607: * Return <code>true</code> if this component is currently painting a tile. 1608: * 1609: * @return Whether the component is painting a tile 1610: */ 1611: public boolean isPaintingTile() 1612: { 1613: return false; 1614: } 1615: 1616: /** 1617: * Get the value of the {@link #requestFocusEnabled} property. 1618: * 1619: * @return The current value of the property 1620: */ 1621: public boolean isRequestFocusEnabled() 1622: { 1623: return requestFocusEnabled; 1624: } 1625: 1626: /** 1627: * Return <code>true</code> if this component is a validation root; this 1628: * will cause calls to {@link #invalidate()} in this component's children 1629: * to be "captured" at this component, and not propagate to its parents. 1630: * For most components this should return <code>false</code>, but some 1631: * components such as {@link JViewport} will want to return 1632: * <code>true</code>. 1633: * 1634: * @return Whether this component is a validation root 1635: */ 1636: public boolean isValidateRoot() 1637: { 1638: return false; 1639: } 1640: 1641: /** 1642: * <p>Paint the component. This is a delicate process, and should only be 1643: * called from the repaint thread, under control of the {@link 1644: * RepaintManager}. Client code should usually call {@link #repaint()} to 1645: * trigger painting.</p> 1646: * 1647: * <p>The body of the <code>paint</code> call involves calling {@link 1648: * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in 1649: * order. If you want to customize painting behavior, you should override 1650: * one of these methods rather than <code>paint</code>.</p> 1651: * 1652: * <p>For more details on the painting sequence, see <a 1653: * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html"> 1654: * this article</a>.</p> 1655: * 1656: * @param g The graphics context to paint with 1657: * 1658: * @see #paintImmediately(Rectangle) 1659: */ 1660: public void paint(Graphics g) 1661: { 1662: RepaintManager rm = RepaintManager.currentManager(this); 1663: // We do a little stunt act here to switch on double buffering if it's 1664: // not already on. If we are not already doublebuffered, then we jump 1665: // into the method paintDoubleBuffered, which turns on the double buffer 1666: // and then calls paint(g) again. In the second call we go into the else 1667: // branch of this if statement and actually paint things to the double 1668: // buffer. When this method completes, the call stack unwinds back to 1669: // paintDoubleBuffered, where the buffer contents is finally drawn to the 1670: // screen. 1671: if (!isPaintingDoubleBuffered && isDoubleBuffered() 1672: && rm.isDoubleBufferingEnabled()) 1673: paintDoubleBuffered(g); 1674: else 1675: { 1676: if (g.getClip() == null) 1677: g.setClip(0, 0, getWidth(), getHeight()); 1678: paintComponent(g); 1679: paintBorder(g); 1680: paintChildren(g); 1681: Rectangle clip = g.getClipBounds(); 1682: if (clip.x == 0 && clip.y == 0 && clip.width == getWidth() 1683: && clip.height == getHeight()) 1684: RepaintManager.currentManager(this).markCompletelyClean(this); 1685: } 1686: } 1687: 1688: /** 1689: * Paint the component's border. This usually means calling {@link 1690: * Border#paintBorder} on the {@link #border} property, if it is 1691: * non-<code>null</code>. You may override this if you wish to customize 1692: * border painting behavior. The border is painted after the component's 1693: * body, but before the component's children. 1694: * 1695: * @param g The graphics context with which to paint the border 1696: * 1697: * @see #paint 1698: * @see #paintChildren 1699: * @see #paintComponent 1700: */ 1701: protected void paintBorder(Graphics g) 1702: { 1703: if (getBorder() != null) 1704: getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight()); 1705: } 1706: 1707: /** 1708: * Paint the component's children. This usually means calling {@link 1709: * Container#paint}, which recursively calls {@link #paint} on any of the 1710: * component's children, with appropriate changes to coordinate space and 1711: * clipping region. You may override this if you wish to customize 1712: * children painting behavior. The children are painted after the 1713: * component's body and border. 1714: * 1715: * @param g The graphics context with which to paint the children 1716: * 1717: * @see #paint 1718: * @see #paintBorder 1719: * @see #paintComponent 1720: */ 1721: protected void paintChildren(Graphics g) 1722: { 1723: Shape originalClip = g.getClip(); 1724: Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache); 1725: g.clipRect(inner.x, inner.y, inner.width, inner.height); 1726: Component[] children = getComponents(); 1727: for (int i = children.length - 1; i >= 0; --i) 1728: { 1729: if (!children[i].isVisible()) 1730: continue; 1731: 1732: Rectangle bounds = children[i].getBounds(rectCache); 1733: Rectangle oldClip = g.getClipBounds(); 1734: if (oldClip == null) 1735: oldClip = bounds; 1736: 1737: if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height)) 1738: continue; 1739: 1740: boolean translated = false; 1741: try 1742: { 1743: g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height); 1744: g.translate(bounds.x, bounds.y); 1745: translated = true; 1746: children[i].paint(g); 1747: } 1748: finally 1749: { 1750: if (translated) 1751: g.translate(-bounds.x, -bounds.y); 1752: g.setClip(oldClip); 1753: } 1754: } 1755: g.setClip(originalClip); 1756: } 1757: 1758: /** 1759: * Paint the component's body. This usually means calling {@link 1760: * ComponentUI#update} on the {@link #ui} property of the component, if 1761: * it is non-<code>null</code>. You may override this if you wish to 1762: * customize the component's body-painting behavior. The component's body 1763: * is painted first, before the border and children. 1764: * 1765: * @param g The graphics context with which to paint the body 1766: * 1767: * @see #paint 1768: * @see #paintBorder 1769: * @see #paintChildren 1770: */ 1771: protected void paintComponent(Graphics g) 1772: { 1773: if (ui != null) 1774: { 1775: Graphics g2 = g; 1776: if (!(g instanceof Graphics2D)) 1777: g2 = g.create(); 1778: ui.update(getComponentGraphics(g2), this); 1779: if (!(g instanceof Graphics2D)) 1780: g2.dispose(); 1781: } 1782: } 1783: 1784: /** 1785: * A variant of {@link #paintImmediately(Rectangle)} which takes 1786: * integer parameters. 1787: * 1788: * @param x The left x coordinate of the dirty region 1789: * @param y The top y coordinate of the dirty region 1790: * @param w The width of the dirty region 1791: * @param h The height of the dirty region 1792: */ 1793: public void paintImmediately(int x, int y, int w, int h) 1794: { 1795: paintImmediately(new Rectangle(x, y, w, h)); 1796: } 1797: 1798: /** 1799: * Transform the provided dirty rectangle for this component into the 1800: * appropriate ancestral {@link JRootPane} and call {@link #paint} on 1801: * that root pane. This method is called from the {@link RepaintManager} 1802: * and should always be called within the painting thread. 1803: * 1804: * <p>This method will acquire a double buffer from the {@link 1805: * RepaintManager} if the component's {@link #doubleBuffered} property is 1806: * <code>true</code> and the <code>paint</code> call is the 1807: * <em>first</em> recursive <code>paint</code> call inside swing.</p> 1808: * 1809: * <p>The method will also modify the provided {@link Graphics} context 1810: * via the {@link #getComponentGraphics} method. If you want to customize 1811: * the graphics object used for painting, you should override that method 1812: * rather than <code>paint</code>.</p> 1813: * 1814: * @param r The dirty rectangle to paint 1815: */ 1816: public void paintImmediately(Rectangle r) 1817: { 1818: // Try to find a root pane for this component. 1819: //Component root = findPaintRoot(r); 1820: Component root = findPaintRoot(r); 1821: // If no paint root is found, then this component is completely overlapped 1822: // by another component and we don't need repainting. 1823: if (root == null) 1824: return; 1825: if (root == null || !root.isShowing()) 1826: return; 1827: 1828: Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root); 1829: if (root instanceof JComponent) 1830: ((JComponent) root).paintImmediately2(rootClip); 1831: else 1832: root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height); 1833: } 1834: 1835: /** 1836: * Performs the actual work of paintImmediatly on the repaint root. 1837: * 1838: * @param r the area to be repainted 1839: */ 1840: void paintImmediately2(Rectangle r) 1841: { 1842: RepaintManager rm = RepaintManager.currentManager(this); 1843: Graphics g = getGraphics(); 1844: g.setClip(r.x, r.y, r.width, r.height); 1845: if (rm.isDoubleBufferingEnabled() && isDoubleBuffered()) 1846: paintDoubleBuffered(g); 1847: else 1848: paintSimple(g); 1849: g.dispose(); 1850: } 1851: 1852: /** 1853: * Performs double buffered repainting. 1854: * 1855: * @param g the graphics context to paint to 1856: */ 1857: void paintDoubleBuffered(Graphics g) 1858: { 1859: 1860: Rectangle r = g.getClipBounds(); 1861: if (r == null) 1862: r = new Rectangle(0, 0, getWidth(), getHeight()); 1863: RepaintManager rm = RepaintManager.currentManager(this); 1864: 1865: // Paint on the offscreen buffer. 1866: Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight()); 1867: Graphics g2 = buffer.getGraphics(); 1868: g2 = getComponentGraphics(g2); 1869: g2.setClip(r.x, r.y, r.width, r.height); 1870: isPaintingDoubleBuffered = true; 1871: paint(g2); 1872: isPaintingDoubleBuffered = false; 1873: g2.dispose(); 1874: 1875: // Paint the buffer contents on screen. 1876: g.drawImage(buffer, 0, 0, this); 1877: } 1878: 1879: /** 1880: * Performs normal painting without double buffering. 1881: * 1882: * @param g the graphics context to use 1883: */ 1884: void paintSimple(Graphics g) 1885: { 1886: Graphics g2 = getComponentGraphics(g); 1887: paint(g2); 1888: } 1889: 1890: /** 1891: * Return a string representation for this component, for use in 1892: * debugging. 1893: * 1894: * @return A string describing this component. 1895: */ 1896: protected String paramString() 1897: { 1898: StringBuffer sb = new StringBuffer(); 1899: sb.append(super.paramString()); 1900: sb.append(",alignmentX=").append(getAlignmentX()); 1901: sb.append(",alignmentY=").append(getAlignmentY()); 1902: sb.append(",border="); 1903: if (getBorder() != null) 1904: sb.append(getBorder()); 1905: sb.append(",maximumSize="); 1906: if (getMaximumSize() != null) 1907: sb.append(getMaximumSize()); 1908: sb.append(",minimumSize="); 1909: if (getMinimumSize() != null) 1910: sb.append(getMinimumSize()); 1911: sb.append(",preferredSize="); 1912: if (getPreferredSize() != null) 1913: sb.append(getPreferredSize()); 1914: return sb.toString(); 1915: } 1916: 1917: /** 1918: * A variant of {@link 1919: * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which 1920: * provides <code>null</code> for the command name. 1921: */ 1922: public void registerKeyboardAction(ActionListener act, 1923: KeyStroke stroke, 1924: int cond) 1925: { 1926: registerKeyboardAction(act, null, stroke, cond); 1927: } 1928: 1929: /* 1930: * There is some charmingly undocumented behavior sun seems to be using 1931: * to simulate the old register/unregister keyboard binding API. It's not 1932: * clear to me why this matters, but we shall endeavour to follow suit. 1933: * 1934: * Two main thing seem to be happening when you do registerKeyboardAction(): 1935: * 1936: * - no actionMap() entry gets created, just an entry in inputMap() 1937: * 1938: * - the inputMap() entry is a proxy class which invokes the the 1939: * binding's actionListener as a target, and which clobbers the command 1940: * name sent in the ActionEvent, providing the binding command name 1941: * instead. 1942: * 1943: * This much you can work out just by asking the input and action maps 1944: * what they contain after making bindings, and watching the event which 1945: * gets delivered to the recipient. Beyond that, it seems to be a 1946: * sun-private solution so I will only immitate it as much as it matters 1947: * to external observers. 1948: */ 1949: private static class ActionListenerProxy 1950: extends AbstractAction 1951: { 1952: ActionListener target; 1953: String bindingCommandName; 1954: 1955: public ActionListenerProxy(ActionListener li, 1956: String cmd) 1957: { 1958: target = li; 1959: bindingCommandName = cmd; 1960: } 1961: 1962: public void actionPerformed(ActionEvent e) 1963: { 1964: ActionEvent derivedEvent = new ActionEvent(e.getSource(), 1965: e.getID(), 1966: bindingCommandName, 1967: e.getModifiers()); 1968: target.actionPerformed(derivedEvent); 1969: } 1970: } 1971: 1972: 1973: /** 1974: * An obsolete method to register a keyboard action on this component. 1975: * You should use <code>getInputMap</code> and <code>getActionMap</code> 1976: * to fetch mapping tables from keystrokes to commands, and commands to 1977: * actions, respectively, and modify those mappings directly. 1978: * 1979: * @param act The action to be registered 1980: * @param cmd The command to deliver in the delivered {@link 1981: * java.awt.event.ActionEvent} 1982: * @param stroke The keystroke to register on 1983: * @param cond One of the values {@link #UNDEFINED_CONDITION}, 1984: * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or 1985: * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must 1986: * be met for the action to be fired 1987: * 1988: * @see #unregisterKeyboardAction 1989: * @see #getConditionForKeyStroke 1990: * @see #resetKeyboardActions 1991: */ 1992: public void registerKeyboardAction(ActionListener act, 1993: String cmd, 1994: KeyStroke stroke, 1995: int cond) 1996: { 1997: getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd)); 1998: } 1999: 2000: public final void setInputMap(int condition, InputMap map) 2001: { 2002: enableEvents(AWTEvent.KEY_EVENT_MASK); 2003: switch (condition) 2004: { 2005: case WHEN_FOCUSED: 2006: inputMap_whenFocused = map; 2007: break; 2008: 2009: case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: 2010: inputMap_whenAncestorOfFocused = map; 2011: break; 2012: 2013: case WHEN_IN_FOCUSED_WINDOW: 2014: inputMap_whenInFocusedWindow = map; 2015: break; 2016: 2017: case UNDEFINED_CONDITION: 2018: default: 2019: throw new IllegalArgumentException(); 2020: } 2021: } 2022: 2023: public final InputMap getInputMap(int condition) 2024: { 2025: enableEvents(AWTEvent.KEY_EVENT_MASK); 2026: switch (condition) 2027: { 2028: case WHEN_FOCUSED: 2029: if (inputMap_whenFocused == null) 2030: inputMap_whenFocused = new InputMap(); 2031: return inputMap_whenFocused; 2032: 2033: case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: 2034: if (inputMap_whenAncestorOfFocused == null) 2035: inputMap_whenAncestorOfFocused = new InputMap(); 2036: return inputMap_whenAncestorOfFocused; 2037: 2038: case WHEN_IN_FOCUSED_WINDOW: 2039: if (inputMap_whenInFocusedWindow == null) 2040: inputMap_whenInFocusedWindow = new InputMap(); 2041: return inputMap_whenInFocusedWindow; 2042: 2043: case UNDEFINED_CONDITION: 2044: default: 2045: return null; 2046: } 2047: } 2048: 2049: public final InputMap getInputMap() 2050: { 2051: return getInputMap(WHEN_FOCUSED); 2052: } 2053: 2054: public final ActionMap getActionMap() 2055: { 2056: if (actionMap == null) 2057: actionMap = new ActionMap(); 2058: return actionMap; 2059: } 2060: 2061: public final void setActionMap(ActionMap map) 2062: { 2063: actionMap = map; 2064: } 2065: 2066: /** 2067: * Return the condition that determines whether a registered action 2068: * occurs in response to the specified keystroke. 2069: * 2070: * @param ks The keystroke to return the condition of 2071: * 2072: * @return One of the values {@link #UNDEFINED_CONDITION}, {@link 2073: * #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link 2074: * #WHEN_IN_FOCUSED_WINDOW} 2075: * 2076: * @deprecated As of 1.3 KeyStrokes can be registered with multiple 2077: * simultaneous conditions. 2078: * 2079: * @see #registerKeyboardAction(ActionListener, KeyStroke, int) 2080: * @see #unregisterKeyboardAction 2081: * @see #resetKeyboardActions 2082: */ 2083: public int getConditionForKeyStroke(KeyStroke ks) 2084: { 2085: if (inputMap_whenFocused != null 2086: && inputMap_whenFocused.get(ks) != null) 2087: return WHEN_FOCUSED; 2088: else if (inputMap_whenAncestorOfFocused != null 2089: && inputMap_whenAncestorOfFocused.get(ks) != null) 2090: return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT; 2091: else if (inputMap_whenInFocusedWindow != null 2092: && inputMap_whenInFocusedWindow.get(ks) != null) 2093: return WHEN_IN_FOCUSED_WINDOW; 2094: else 2095: return UNDEFINED_CONDITION; 2096: } 2097: 2098: /** 2099: * Get the ActionListener (typically an {@link Action} object) which is 2100: * associated with a particular keystroke. 2101: * 2102: * @param ks The keystroke to retrieve the action of 2103: * 2104: * @return The action associated with the specified keystroke 2105: * 2106: * @deprecated Use {@link #getActionMap()} 2107: */ 2108: public ActionListener getActionForKeyStroke(KeyStroke ks) 2109: { 2110: Object cmd = getInputMap().get(ks); 2111: if (cmd != null) 2112: { 2113: if (cmd instanceof ActionListenerProxy) 2114: return (ActionListenerProxy) cmd; 2115: else if (cmd instanceof String) 2116: return getActionMap().get(cmd); 2117: } 2118: return null; 2119: } 2120: 2121: /** 2122: * A hook for subclasses which want to customize event processing. 2123: */ 2124: protected void processComponentKeyEvent(KeyEvent e) 2125: { 2126: // This method does nothing, it is meant to be overridden by subclasses. 2127: } 2128: 2129: /** 2130: * Override the default key dispatch system from Component to hook into 2131: * the swing {@link InputMap} / {@link ActionMap} system. 2132: * 2133: * See <a 2134: * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html"> 2135: * this report</a> for more details, it's somewhat complex. 2136: */ 2137: protected void processKeyEvent(KeyEvent e) 2138: { 2139: // let the AWT event processing send KeyEvents to registered listeners 2140: super.processKeyEvent(e); 2141: processComponentKeyEvent(e); 2142: 2143: if (e.isConsumed()) 2144: return; 2145: 2146: // Input maps are checked in this order: 2147: // 1. The focused component's WHEN_FOCUSED map is checked. 2148: // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map. 2149: // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused 2150: // component's parent, then its parent's parent, and so on. 2151: // Note: Input maps for disabled components are skipped. 2152: // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in 2153: // the focused window are searched. 2154: 2155: if (processKeyBinding(KeyStroke.getKeyStrokeForEvent(e), 2156: e, WHEN_FOCUSED, e.getID() == KeyEvent.KEY_PRESSED)) 2157: // This is step 1 from above comment. 2158: e.consume(); 2159: else if (processKeyBinding(KeyStroke.getKeyStrokeForEvent(e), 2160: e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, 2161: e.getID() == KeyEvent.KEY_PRESSED)) 2162: // This is step 2 from above comment. 2163: e.consume(); 2164: else 2165: { 2166: // This is step 3 from above comment. 2167: Container current = this; 2168: while ((current = current.getParent()) instanceof JComponent) 2169: { 2170: if (((JComponent)current).processKeyBinding 2171: (KeyStroke.getKeyStrokeForEvent(e), e, 2172: WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, 2173: e.getID() == KeyEvent.KEY_PRESSED)) 2174: { 2175: e.consume(); 2176: break; 2177: } 2178: if (current instanceof Window || current instanceof Applet 2179: || current instanceof JInternalFrame) 2180: break; 2181: } 2182: if (e.isConsumed()) 2183: return; 2184: 2185: // This is step 4 from above comment. 2186: // FIXME: Implement. Note, should use ComponentInputMaps rather 2187: // than walking the entire containment hierarchy. 2188: } 2189: } 2190: 2191: protected boolean processKeyBinding(KeyStroke ks, 2192: KeyEvent e, 2193: int condition, 2194: boolean pressed) 2195: { 2196: if (isEnabled()) 2197: { 2198: Action act = null; 2199: InputMap map = getInputMap(condition); 2200: if (map != null) 2201: { 2202: Object cmd = map.get(ks); 2203: if (cmd != null) 2204: { 2205: if (cmd instanceof ActionListenerProxy) 2206: act = (Action) cmd; 2207: else 2208: act = (Action) getActionMap().get(cmd); 2209: } 2210: } 2211: if (act != null && act.isEnabled()) 2212: return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers()); 2213: } 2214: return false; 2215: } 2216: 2217: /** 2218: * Remove a keyboard action registry. 2219: * 2220: * @param aKeyStroke The keystroke to unregister 2221: * 2222: * @see #registerKeyboardAction(ActionListener, KeyStroke, int) 2223: * @see #getConditionForKeyStroke 2224: * @see #resetKeyboardActions 2225: */ 2226: public void unregisterKeyboardAction(KeyStroke aKeyStroke) 2227: { 2228: // FIXME: Must be implemented. 2229: } 2230: 2231: 2232: /** 2233: * Reset all keyboard action registries. 2234: * 2235: * @see #registerKeyboardAction(ActionListener, KeyStroke, int) 2236: * @see #unregisterKeyboardAction 2237: * @see #getConditionForKeyStroke 2238: */ 2239: public void resetKeyboardActions() 2240: { 2241: if (inputMap_whenFocused != null) 2242: inputMap_whenFocused.clear(); 2243: if (inputMap_whenAncestorOfFocused != null) 2244: inputMap_whenAncestorOfFocused.clear(); 2245: if (inputMap_whenInFocusedWindow != null) 2246: inputMap_whenInFocusedWindow.clear(); 2247: if (actionMap != null) 2248: actionMap.clear(); 2249: } 2250: 2251: /** 2252: * Mark the described region of this component as dirty in the current 2253: * {@link RepaintManager}. This will queue an asynchronous repaint using 2254: * the system painting thread in the near future. 2255: * 2256: * @param tm ignored 2257: * @param x coordinate of the region to mark as dirty 2258: * @param y coordinate of the region to mark as dirty 2259: * @param width dimension of the region to mark as dirty 2260: * @param height dimension of the region to mark as dirty 2261: */ 2262: public void repaint(long tm, int x, int y, int width, int height) 2263: { 2264: Rectangle dirty = new Rectangle(x, y, width, height); 2265: Rectangle vis = getVisibleRect(); 2266: dirty = dirty.intersection(vis); 2267: RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y, 2268: dirty.width, 2269: dirty.height); 2270: } 2271: 2272: /** 2273: * Mark the described region of this component as dirty in the current 2274: * {@link RepaintManager}. This will queue an asynchronous repaint using 2275: * the system painting thread in the near future. 2276: * 2277: * @param r The rectangle to mark as dirty 2278: */ 2279: public void repaint(Rectangle r) 2280: { 2281: repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(), 2282: (int) r.getHeight()); 2283: } 2284: 2285: /** 2286: * Request focus on the default component of this component's {@link 2287: * FocusTraversalPolicy}. 2288: * 2289: * @return The result of {@link #requestFocus()} 2290: * 2291: * @deprecated Use {@link #requestFocus()} on the default component provided 2292: * from the {@link FocusTraversalPolicy} instead. 2293: */ 2294: public boolean requestDefaultFocus() 2295: { 2296: return false; 2297: } 2298: 2299: /** 2300: * Queue a an invalidation and revalidation of this component, using 2301: * {@link RepaintManager#addInvalidComponent}. 2302: */ 2303: public void revalidate() 2304: { 2305: if (! EventQueue.isDispatchThread()) 2306: SwingUtilities.invokeLater(new Runnable() 2307: { 2308: public void run() 2309: { 2310: revalidate(); 2311: } 2312: }); 2313: else 2314: { 2315: invalidate(); 2316: RepaintManager.currentManager(this).addInvalidComponent(this); 2317: } 2318: } 2319: 2320: /** 2321: * Calls <code>scrollRectToVisible</code> on the component's parent. 2322: * Components which can service this call should override. 2323: * 2324: * @param r The rectangle to make visible 2325: */ 2326: public void scrollRectToVisible(Rectangle r) 2327: { 2328: Component p = getParent(); 2329: if (p instanceof JComponent) 2330: ((JComponent) p).scrollRectToVisible(r); 2331: } 2332: 2333: /** 2334: * Set the value of the {@link #alignmentX} property. 2335: * 2336: * @param a The new value of the property 2337: */ 2338: public void setAlignmentX(float a) 2339: { 2340: alignmentX = a; 2341: } 2342: 2343: /** 2344: * Set the value of the {@link #alignmentY} property. 2345: * 2346: * @param a The new value of the property 2347: */ 2348: public void setAlignmentY(float a) 2349: { 2350: alignmentY = a; 2351: } 2352: 2353: /** 2354: * Set the value of the {@link #autoscrolls} property. 2355: * 2356: * @param a The new value of the property 2357: */ 2358: public void setAutoscrolls(boolean a) 2359: { 2360: autoscrolls = a; 2361: } 2362: 2363: /** 2364: * Set the value of the {@link #debugGraphicsOptions} property. 2365: * 2366: * @param debugOptions The new value of the property 2367: */ 2368: public void setDebugGraphicsOptions(int debugOptions) 2369: { 2370: debugGraphicsOptions = debugOptions; 2371: } 2372: 2373: /** 2374: * Set the value of the {@link #doubleBuffered} property. 2375: * 2376: * @param db The new value of the property 2377: */ 2378: public void setDoubleBuffered(boolean db) 2379: { 2380: doubleBuffered = db; 2381: } 2382: 2383: /** 2384: * Set the value of the <code>enabled</code> property. 2385: * 2386: * @param enable The new value of the property 2387: */ 2388: public void setEnabled(boolean enable) 2389: { 2390: if (enable == isEnabled()) 2391: return; 2392: super.setEnabled(enable); 2393: firePropertyChange("enabled", !enable, enable); 2394: repaint(); 2395: } 2396: 2397: /** 2398: * Set the value of the <code>font</code> property. 2399: * 2400: * @param f The new value of the property 2401: */ 2402: public void setFont(Font f) 2403: { 2404: if (f == getFont()) 2405: return; 2406: super.setFont(f); 2407: revalidate(); 2408: repaint(); 2409: } 2410: 2411: /** 2412: * Set the value of the <code>background</code> property. 2413: * 2414: * @param bg The new value of the property 2415: */ 2416: public void setBackground(Color bg) 2417: { 2418: if (bg == getBackground()) 2419: return; 2420: super.setBackground(bg); 2421: repaint(); 2422: } 2423: 2424: /** 2425: * Set the value of the <code>foreground</code> property. 2426: * 2427: * @param fg The new value of the property 2428: */ 2429: public void setForeground(Color fg) 2430: { 2431: if (fg == getForeground()) 2432: return; 2433: super.setForeground(fg); 2434: repaint(); 2435: } 2436: 2437: /** 2438: * Set the value of the {@link #maximumSize} property. 2439: * 2440: * @param max The new value of the property 2441: */ 2442: public void setMaximumSize(Dimension max) 2443: { 2444: Dimension oldMaximumSize = maximumSize; 2445: maximumSize = max; 2446: firePropertyChange("maximumSize", oldMaximumSize, maximumSize); 2447: } 2448: 2449: /** 2450: * Set the value of the {@link #minimumSize} property. 2451: * 2452: * @param min The new value of the property 2453: */ 2454: public void setMinimumSize(Dimension min) 2455: { 2456: Dimension oldMinimumSize = minimumSize; 2457: minimumSize = min; 2458: firePropertyChange("minimumSize", oldMinimumSize, minimumSize); 2459: } 2460: 2461: /** 2462: * Set the value of the {@link #preferredSize} property. 2463: * 2464: * @param pref The new value of the property 2465: */ 2466: public void setPreferredSize(Dimension pref) 2467: { 2468: Dimension oldPreferredSize = preferredSize; 2469: preferredSize = pref; 2470: firePropertyChange("preferredSize", oldPreferredSize, preferredSize); 2471: } 2472: 2473: /** 2474: * Set the specified component to be the next component in the 2475: * focus cycle, overriding the {@link FocusTraversalPolicy} for 2476: * this component. 2477: * 2478: * @param aComponent The component to set as the next focusable 2479: * 2480: * @deprecated Use FocusTraversalPolicy instead 2481: */ 2482: public void setNextFocusableComponent(Component aComponent) 2483: { 2484: // TODO: Implement this properly. 2485: } 2486: 2487: /** 2488: * Set the value of the {@link #requestFocusEnabled} property. 2489: * 2490: * @param e The new value of the property 2491: */ 2492: public void setRequestFocusEnabled(boolean e) 2493: { 2494: requestFocusEnabled = e; 2495: } 2496: 2497: /** 2498: * Get the value of the {@link #transferHandler} property. 2499: * 2500: * @return The current value of the property 2501: * 2502: * @see #setTransferHandler 2503: */ 2504: 2505: public TransferHandler getTransferHandler() 2506: { 2507: return transferHandler; 2508: } 2509: 2510: /** 2511: * Set the value of the {@link #transferHandler} property. 2512: * 2513: * @param newHandler The new value of the property 2514: * 2515: * @see #getTransferHandler 2516: */ 2517: 2518: public void setTransferHandler(TransferHandler newHandler) 2519: { 2520: if (transferHandler == newHandler) 2521: return; 2522: 2523: TransferHandler oldHandler = transferHandler; 2524: transferHandler = newHandler; 2525: firePropertyChange("transferHandler", oldHandler, newHandler); 2526: } 2527: 2528: /** 2529: * Set the value of the {@link #opaque} property. 2530: * 2531: * @param isOpaque The new value of the property 2532: * 2533: * @see ComponentUI#update 2534: */ 2535: public void setOpaque(boolean isOpaque) 2536: { 2537: boolean oldOpaque = opaque; 2538: opaque = isOpaque; 2539: firePropertyChange("opaque", oldOpaque, opaque); 2540: } 2541: 2542: /** 2543: * Set the value of the visible property. 2544: * 2545: * If the value is changed, then the AncestorListeners of this component 2546: * and all its children (recursivly) are notified. 2547: * 2548: * @param v The new value of the property 2549: */ 2550: public void setVisible(boolean v) 2551: { 2552: // No need to do anything if the actual value doesn't change. 2553: if (isVisible() == v) 2554: return; 2555: 2556: super.setVisible(v); 2557: 2558: // Notify AncestorListeners. 2559: if (v == true) 2560: fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED); 2561: else 2562: fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED); 2563: 2564: Container parent = getParent(); 2565: if (parent != null) 2566: parent.repaint(getX(), getY(), getWidth(), getHeight()); 2567: revalidate(); 2568: } 2569: 2570: /** 2571: * Call {@link #paint}. 2572: * 2573: * @param g The graphics context to paint into 2574: */ 2575: public void update(Graphics g) 2576: { 2577: paint(g); 2578: } 2579: 2580: /** 2581: * Get the value of the UIClassID property. This property should be a key 2582: * in the {@link UIDefaults} table managed by {@link UIManager}, the 2583: * value of which is the name of a class to load for the component's 2584: * {@link #ui} property. 2585: * 2586: * @return A "symbolic" name which will map to a class to use for the 2587: * component's UI, such as <code>"ComponentUI"</code> 2588: * 2589: * @see #setUI 2590: * @see #updateUI 2591: */ 2592: public String getUIClassID() 2593: { 2594: return "ComponentUI"; 2595: } 2596: 2597: /** 2598: * Install a new UI delegate as the component's {@link #ui} property. In 2599: * the process, this will call {@link ComponentUI#uninstallUI} on any 2600: * existing value for the {@link #ui} property, and {@link 2601: * ComponentUI#installUI} on the new UI delegate. 2602: * 2603: * @param newUI The new UI delegate to install 2604: * 2605: * @see #updateUI 2606: * @see #getUIClassID 2607: */ 2608: protected void setUI(ComponentUI newUI) 2609: { 2610: if (ui != null) 2611: ui.uninstallUI(this); 2612: 2613: ComponentUI oldUI = ui; 2614: ui = newUI; 2615: 2616: if (ui != null) 2617: ui.installUI(this); 2618: 2619: firePropertyChange("UI", oldUI, newUI); 2620: revalidate(); 2621: repaint(); 2622: } 2623: 2624: /** 2625: * This method should be overridden in subclasses. In JComponent, the 2626: * method does nothing. In subclasses, it should a UI delegate 2627: * (corresponding to the symbolic name returned from {@link 2628: * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI} 2629: * with the new delegate. 2630: */ 2631: public void updateUI() 2632: { 2633: System.out.println("update UI not overwritten in class: " + this); 2634: } 2635: 2636: public static Locale getDefaultLocale() 2637: { 2638: return defaultLocale; 2639: } 2640: 2641: public static void setDefaultLocale(Locale l) 2642: { 2643: defaultLocale = l; 2644: } 2645: 2646: /** 2647: * Returns the currently set input verifier for this component. 2648: * 2649: * @return the input verifier, or <code>null</code> if none 2650: */ 2651: public InputVerifier getInputVerifier() 2652: { 2653: return inputVerifier; 2654: } 2655: 2656: /** 2657: * Sets the input verifier to use by this component. 2658: * 2659: * @param verifier the input verifier, or <code>null</code> 2660: */ 2661: public void setInputVerifier(InputVerifier verifier) 2662: { 2663: InputVerifier oldVerifier = inputVerifier; 2664: inputVerifier = verifier; 2665: firePropertyChange("inputVerifier", oldVerifier, verifier); 2666: } 2667: 2668: /** 2669: * @since 1.3 2670: */ 2671: public boolean getVerifyInputWhenFocusTarget() 2672: { 2673: return verifyInputWhenFocusTarget; 2674: } 2675: 2676: /** 2677: * @since 1.3 2678: */ 2679: public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget) 2680: { 2681: if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget) 2682: return; 2683: 2684: this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget; 2685: firePropertyChange("verifyInputWhenFocusTarget", 2686: ! verifyInputWhenFocusTarget, 2687: verifyInputWhenFocusTarget); 2688: } 2689: 2690: /** 2691: * Requests that this component gets the input focus if the 2692: * requestFocusEnabled property is set to <code>true</code>. 2693: * This also means that this component's top-level window becomes 2694: * the focused window, if that is not already the case. 2695: * 2696: * The preconditions that have to be met to become a focus owner is that 2697: * the component must be displayable, visible and focusable. 2698: * 2699: * Note that this signals only a request for becoming focused. There are 2700: * situations in which it is not possible to get the focus. So developers 2701: * should not assume that the component has the focus until it receives 2702: * a {@link java.awt.event.FocusEvent} with a value of 2703: * {@link java.awt.event.FocusEvent#FOCUS_GAINED}. 2704: * 2705: * @see Component#requestFocus() 2706: */ 2707: public void requestFocus() 2708: { 2709: if (isRequestFocusEnabled()) 2710: super.requestFocus(); 2711: } 2712: 2713: /** 2714: * This method is overridden to make it public so that it can be used 2715: * by look and feel implementations. 2716: * 2717: * You should not use this method directly. Instead you are strongly 2718: * encouraged to call {@link #requestFocus()} or 2719: * {@link #requestFocusInWindow()} instead. 2720: * 2721: * @param temporary if the focus change is temporary 2722: * 2723: * @return <code>false</code> if the focus change request will definitly 2724: * fail, <code>true</code> if it will likely succeed 2725: * 2726: * @see Component#requestFocus(boolean) 2727: * 2728: * @since 1.4 2729: */ 2730: public boolean requestFocus(boolean temporary) 2731: { 2732: return super.requestFocus(temporary); 2733: } 2734: 2735: /** 2736: * Requests that this component gets the input focus if the top level 2737: * window that contains this component has the focus and the 2738: * requestFocusEnabled property is set to <code>true</code>. 2739: * 2740: * The preconditions that have to be met to become a focus owner is that 2741: * the component must be displayable, visible and focusable. 2742: * 2743: * Note that this signals only a request for becoming focused. There are 2744: * situations in which it is not possible to get the focus. So developers 2745: * should not assume that the component has the focus until it receives 2746: * a {@link java.awt.event.FocusEvent} with a value of 2747: * {@link java.awt.event.FocusEvent#FOCUS_GAINED}. 2748: * 2749: * @return <code>false</code> if the focus change request will definitly 2750: * fail, <code>true</code> if it will likely succeed 2751: * 2752: * @see Component#requestFocusInWindow() 2753: */ 2754: public boolean requestFocusInWindow() 2755: { 2756: if (isRequestFocusEnabled()) 2757: return super.requestFocusInWindow(); 2758: else 2759: return false; 2760: } 2761: 2762: /** 2763: * This method is overridden to make it public so that it can be used 2764: * by look and feel implementations. 2765: * 2766: * You should not use this method directly. Instead you are strongly 2767: * encouraged to call {@link #requestFocus()} or 2768: * {@link #requestFocusInWindow()} instead. 2769: * 2770: * @param temporary if the focus change is temporary 2771: * 2772: * @return <code>false</code> if the focus change request will definitly 2773: * fail, <code>true</code> if it will likely succeed 2774: * 2775: * @see Component#requestFocus(boolean) 2776: * 2777: * @since 1.4 2778: */ 2779: public boolean requestFocusInWindow(boolean temporary) 2780: { 2781: return super.requestFocusInWindow(temporary); 2782: } 2783: 2784: /** 2785: * Receives notification if this component is added to a parent component. 2786: * 2787: * Notification is sent to all registered AncestorListeners about the 2788: * new parent. 2789: * 2790: * This method sets up ActionListeners for all registered KeyStrokes of 2791: * this component in the chain of parent components. 2792: * 2793: * A PropertyChange event is fired to indicate that the ancestor property 2794: * has changed. 2795: * 2796: * This method is used internally and should not be used in applications. 2797: */ 2798: public void addNotify() 2799: { 2800: super.addNotify(); 2801: 2802: // let parents inherit the keybord mapping 2803: InputMap input = getInputMap(); 2804: ActionMap actions = getActionMap(); 2805: 2806: Container parent = getParent(); 2807: while ((parent != null) && (parent instanceof JComponent)) 2808: { 2809: JComponent jParent = (JComponent) parent; 2810: InputMap parentInput = jParent.getInputMap(); 2811: ActionMap parentAction = jParent.getActionMap(); 2812: 2813: KeyStroke[] ikeys = input.keys(); 2814: for (int i = 0; i < ikeys.length; i++) 2815: { 2816: Object o = input.get(ikeys[i]); 2817: parentInput.put(ikeys[i], o); 2818: } 2819: 2820: Object[] akeys = actions.keys(); 2821: for (int i = 0; i < akeys.length; i++) 2822: { 2823: Action a = actions.get(akeys[i]); 2824: parentAction.put(akeys[i], a); 2825: } 2826: 2827: parent = jParent.getParent(); 2828: } 2829: 2830: // Notify AncestorListeners. 2831: fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED); 2832: 2833: // fire property change event for 'ancestor' 2834: firePropertyChange("ancestor", null, parent); 2835: } 2836: 2837: /** 2838: * Receives notification that this component no longer has a parent. 2839: * 2840: * This method sends an AncestorEvent to all registered AncestorListeners, 2841: * notifying them that the parent is gone. 2842: * 2843: * The keybord actions of this component are removed from the parent and 2844: * its ancestors. 2845: * 2846: * A PropertyChangeEvent is fired to indicate that the 'ancestor' property 2847: * has changed. 2848: * 2849: * This method is called before the component is actually removed from 2850: * its parent, so the parent is still visible through 2851: * {@link Component#getParent}. 2852: */ 2853: public void removeNotify() 2854: { 2855: super.removeNotify(); 2856: 2857: // let parents inherit the keybord mapping 2858: InputMap input = getInputMap(); 2859: ActionMap actions = getActionMap(); 2860: 2861: Container parent = getParent(); 2862: while ((parent != null) && (parent instanceof JComponent)) 2863: { 2864: JComponent jParent = (JComponent) parent; 2865: InputMap parentInput = jParent.getInputMap(); 2866: ActionMap parentAction = jParent.getActionMap(); 2867: 2868: KeyStroke[] ikeys = input.allKeys(); 2869: for (int i = 0; i < ikeys.length; i++) 2870: { 2871: parentInput.remove(ikeys[i]); 2872: } 2873: 2874: Object[] akeys = actions.allKeys(); 2875: for (int i = 0; i < akeys.length; i++) 2876: { 2877: parentAction.remove(akeys[i]); 2878: } 2879: 2880: parent = jParent.getParent(); 2881: } 2882: 2883: // Notify ancestor listeners. 2884: fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED); 2885: 2886: // fire property change event for 'ancestor' 2887: firePropertyChange("ancestor", parent, null); 2888: } 2889: 2890: /** 2891: * Returns <code>true</code> if the coordinates (x, y) lie within 2892: * the bounds of this component and <code>false</code> otherwise. 2893: * x and y are relative to the coordinate space of the component. 2894: * 2895: * @param x the X coordinate of the point to check 2896: * @param y the Y coordinate of the point to check 2897: * 2898: * @return <code>true</code> if the specified point lies within the bounds 2899: * of this component, <code>false</code> otherwise 2900: */ 2901: public boolean contains(int x, int y) 2902: { 2903: if (ui == null) 2904: return super.contains(x, y); 2905: else 2906: return ui.contains(this, x, y); 2907: } 2908: 2909: /** 2910: * Disables this component. 2911: * 2912: * @deprecated replaced by {@link #setEnabled(boolean)} 2913: */ 2914: public void disable() 2915: { 2916: super.disable(); 2917: } 2918: 2919: /** 2920: * Enables this component. 2921: * 2922: * @deprecated replaced by {@link #setEnabled(boolean)} 2923: */ 2924: public void enable() 2925: { 2926: super.enable(); 2927: } 2928: 2929: /** 2930: * Returns the Graphics context for this component. This can be used 2931: * to draw on a component. 2932: * 2933: * @return the Graphics context for this component 2934: */ 2935: public Graphics getGraphics() 2936: { 2937: return super.getGraphics(); 2938: } 2939: 2940: /** 2941: * Returns the X coordinate of the upper left corner of this component. 2942: * Prefer this method over {@link #getBounds} or {@link #getLocation} 2943: * because it does not cause any heap allocation. 2944: * 2945: * @return the X coordinate of the upper left corner of the component 2946: */ 2947: public int getX() 2948: { 2949: return super.getX(); 2950: } 2951: 2952: /** 2953: * Returns the Y coordinate of the upper left corner of this component. 2954: * Prefer this method over {@link #getBounds} or {@link #getLocation} 2955: * because it does not cause any heap allocation. 2956: * 2957: * @return the Y coordinate of the upper left corner of the component 2958: */ 2959: public int getY() 2960: { 2961: return super.getY(); 2962: } 2963: 2964: /** 2965: * Returns the height of this component. Prefer this method over 2966: * {@link #getBounds} or {@link #getSize} because it does not cause 2967: * any heap allocation. 2968: * 2969: * @return the height of the component 2970: */ 2971: public int getHeight() 2972: { 2973: return super.getHeight(); 2974: } 2975: 2976: /** 2977: * Returns the width of this component. Prefer this method over 2978: * {@link #getBounds} or {@link #getSize} because it does not cause 2979: * any heap allocation. 2980: * 2981: * @return the width of the component 2982: */ 2983: public int getWidth() 2984: { 2985: return super.getWidth(); 2986: } 2987: 2988: /** 2989: * Return all <code>PropertyChangeListener</code> objects registered. 2990: * 2991: * @return The set of <code>PropertyChangeListener</code> objects 2992: */ 2993: public PropertyChangeListener[] getPropertyChangeListeners() 2994: { 2995: if (changeSupport == null) 2996: return new PropertyChangeListener[0]; 2997: else 2998: return changeSupport.getPropertyChangeListeners(); 2999: } 3000: 3001: /** 3002: * Prints this component to the given Graphics context. A call to this 3003: * method results in calls to the methods {@link #printComponent}, 3004: * {@link #printBorder} and {@link #printChildren} in this order. 3005: * 3006: * Double buffering is temporarily turned off so the painting goes directly 3007: * to the supplied Graphics context. 3008: * 3009: * @param g the Graphics context to print onto 3010: */ 3011: public void print(Graphics g) 3012: { 3013: boolean doubleBufferState = isDoubleBuffered(); 3014: setDoubleBuffered(false); 3015: printComponent(g); 3016: printBorder(g); 3017: printChildren(g); 3018: setDoubleBuffered(doubleBufferState); 3019: } 3020: 3021: /** 3022: * Prints this component to the given Graphics context. This invokes 3023: * {@link #print}. 3024: * 3025: * @param g the Graphics context to print onto 3026: */ 3027: public void printAll(Graphics g) 3028: { 3029: print(g); 3030: } 3031: 3032: /** 3033: * Prints this component to the specified Graphics context. The default 3034: * behaviour is to invoke {@link #paintComponent}. Override this 3035: * if you want special behaviour for printing. 3036: * 3037: * @param g the Graphics context to print onto 3038: * 3039: * @since 1.3 3040: */ 3041: public void printComponent(Graphics g) 3042: { 3043: paintComponent(g); 3044: } 3045: 3046: /** 3047: * Print this component's children to the specified Graphics context. 3048: * The default behaviour is to invoke {@link #paintChildren}. Override this 3049: * if you want special behaviour for printing. 3050: * 3051: * @param g the Graphics context to print onto 3052: * 3053: * @since 1.3 3054: */ 3055: public void printChildren(Graphics g) 3056: { 3057: paintChildren(g); 3058: } 3059: 3060: /** 3061: * Print this component's border to the specified Graphics context. 3062: * The default behaviour is to invoke {@link #paintBorder}. Override this 3063: * if you want special behaviour for printing. 3064: * 3065: * @param g the Graphics context to print onto 3066: * 3067: * @since 1.3 3068: */ 3069: public void printBorder(Graphics g) 3070: { 3071: paintBorder(g); 3072: } 3073: 3074: /** 3075: * Processes mouse motion event, like dragging and moving. 3076: * 3077: * @param ev the MouseEvent describing the mouse motion 3078: */ 3079: protected void processMouseMotionEvent(MouseEvent ev) 3080: { 3081: super.processMouseMotionEvent(ev); 3082: } 3083: 3084: /** 3085: * Moves and resizes the component. 3086: * 3087: * @param x the new horizontal location 3088: * @param y the new vertial location 3089: * @param w the new width 3090: * @param h the new height 3091: */ 3092: public void reshape(int x, int y, int w, int h) 3093: { 3094: int oldX = getX(); 3095: int oldY = getY(); 3096: super.reshape(x, y, w, h); 3097: // Notify AncestorListeners. 3098: if (oldX != getX() || oldY != getY()) 3099: fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED); 3100: } 3101: 3102: /** 3103: * Fires an AncestorEvent to this component's and all of its child 3104: * component's AncestorListeners. 3105: * 3106: * @param ancestor the component that triggered the event 3107: * @param id the kind of ancestor event that should be fired 3108: */ 3109: void fireAncestorEvent(JComponent ancestor, int id) 3110: { 3111: // Fire event for registered ancestor listeners of this component. 3112: AncestorListener[] listeners = getAncestorListeners(); 3113: if (listeners.length > 0) 3114: { 3115: AncestorEvent ev = new AncestorEvent(this, id, 3116: ancestor, ancestor.getParent()); 3117: for (int i = 0; i < listeners.length; i++) 3118: { 3119: switch (id) 3120: { 3121: case AncestorEvent.ANCESTOR_MOVED: 3122: listeners[i].ancestorMoved(ev); 3123: break; 3124: case AncestorEvent.ANCESTOR_ADDED: 3125: listeners[i].ancestorAdded(ev); 3126: break; 3127: case AncestorEvent.ANCESTOR_REMOVED: 3128: listeners[i].ancestorRemoved(ev); 3129: break; 3130: } 3131: } 3132: } 3133: // Dispatch event to all children. 3134: Component[] children = getComponents(); 3135: for (int i = 0; i < children.length; i++) 3136: { 3137: if (!(children[i] instanceof JComponent)) 3138: continue; 3139: JComponent jc = (JComponent) children[i]; 3140: jc.fireAncestorEvent(ancestor, id); 3141: } 3142: } 3143: 3144: /** 3145: * Finds a suitable paint root for painting this component. This method first 3146: * checks if this component is overlapped using 3147: * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then 3148: * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque 3149: * component for this paint root. If no paint is necessary, then we return 3150: * <code>null</code>. 3151: * 3152: * @param c the clip of this component 3153: * 3154: * @return the paint root or <code>null</code> if no painting is necessary 3155: */ 3156: private Component findPaintRoot(Rectangle c) 3157: { 3158: Component p = findOverlapFreeParent(c); 3159: if (p == null) 3160: return null; 3161: Component root = findOpaqueParent(p); 3162: return root; 3163: } 3164: 3165: /** 3166: * Scans the containment hierarchy upwards for components that overlap the 3167: * this component in the specified clip. This method returns 3168: * <code>this</code>, if no component overlaps this component. It returns 3169: * <code>null</code> if another component completely covers this component 3170: * in the specified clip (no repaint necessary). If another component partly 3171: * overlaps this component in the specified clip, then the parent of this 3172: * component is returned (this is the component that must be used as repaint 3173: * root). For efficient lookup, the method 3174: * {@link #isOptimizedDrawingEnabled()} is used. 3175: * 3176: * @param clip the clip of this component 3177: * 3178: * @return the paint root, or <code>null</code> if no paint is necessary 3179: */ 3180: private Component findOverlapFreeParent(Rectangle clip) 3181: { 3182: Rectangle currentClip = clip; 3183: Component found = this; 3184: Container parent = this; 3185: while (parent != null && !(parent instanceof Window)) 3186: { 3187: Container newParent = parent.getParent(); 3188: if (newParent == null) 3189: break; 3190: // If the parent is optimizedDrawingEnabled, then its children are 3191: // tiled and cannot have an overlapping child. Go directly to next 3192: // parent. 3193: if (newParent instanceof JComponent 3194: && ((JComponent) newParent).isOptimizedDrawingEnabled()) 3195: { 3196: parent = newParent; 3197: continue; 3198: } 3199: 3200: // First we must check if the new parent itself somehow clips the 3201: // target rectangle. This can happen in JViewports. 3202: Rectangle parRect = new Rectangle(0, 0, newParent.getWidth(), 3203: newParent.getHeight()); 3204: Rectangle target = SwingUtilities.convertRectangle(found, 3205: currentClip, 3206: newParent); 3207: if (target.contains(parRect) || target.intersects(parRect)) 3208: { 3209: found = newParent; 3210: currentClip = target; 3211: parent = newParent; 3212: continue; 3213: } 3214: 3215: // Otherwise we must check if one of the children of this parent 3216: // overlaps with the current component. 3217: Component[] children = newParent.getComponents(); 3218: // This flag is used to skip components that are 'below' the component 3219: // in question. 3220: boolean skip = true; 3221: for (int i = children.length - 1; i >= 0; i--) 3222: { 3223: if (children[i] == parent) 3224: skip = false; 3225: if (skip) 3226: continue; 3227: Component c = children[i]; 3228: Rectangle compBounds = c.getBounds(); 3229: // If the component completely overlaps the clip in question, we 3230: // don't need to repaint. Return null. 3231: if (compBounds.contains(target)) 3232: return null; 3233: if (compBounds.intersects(target)) 3234: { 3235: // We found a parent whose children overlap with our current 3236: // component. Make this the current component. 3237: found = newParent; 3238: currentClip = target; 3239: break; 3240: } 3241: } 3242: parent = newParent; 3243: } 3244: return found; 3245: } 3246: 3247: /** 3248: * Finds the nearest component to <code>c</code> (upwards in the containment 3249: * hierarchy), that is opaque. If <code>c</code> itself is opaque, 3250: * this returns <code>c</code> itself. 3251: * 3252: * @param c the start component for the search 3253: * @return the nearest component to <code>c</code> (upwards in the containment 3254: * hierarchy), that is opaque; If <code>c</code> itself is opaque, 3255: * this returns <code>c</code> itself 3256: */ 3257: private Component findOpaqueParent(Component c) 3258: { 3259: Component found = c; 3260: while (true) 3261: { 3262: if ((found instanceof JComponent) && ((JComponent) found).isOpaque()) 3263: break; 3264: else if (!(found instanceof JComponent)) 3265: break; 3266: Container p = found.getParent(); 3267: if (p == null) 3268: break; 3269: else 3270: found = p; 3271: } 3272: return found; 3273: } 3274: }
GNU Classpath (0.19) |