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