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