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