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