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