home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / swing / JComponent.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  110.2 KB  |  3,188 lines

  1. /*
  2.  * @(#)JComponent.java    2.53 98/03/04
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20. package java.awt.swing;
  21.  
  22.  
  23. import java.awt.Component;
  24. import java.awt.Container;
  25. import java.awt.Color;
  26. import java.awt.Cursor;
  27. import java.awt.Window;
  28. import java.awt.Font;
  29. import java.awt.FontMetrics;
  30. import java.awt.Frame;
  31. import java.awt.Dimension;
  32. import java.awt.Insets;
  33. import java.awt.Graphics;
  34. import java.awt.Window;
  35. import java.awt.AWTEvent;
  36. import java.awt.Rectangle;
  37. import java.util.Hashtable;
  38. import java.util.Dictionary;
  39. import java.util.Enumeration;
  40. import java.util.Locale;
  41. import java.util.Vector;
  42. import java.awt.Point;
  43. import java.awt.Image;
  44. import java.awt.LayoutManager2;
  45. import java.awt.Color;
  46.  
  47. import java.awt.event.*;
  48. import java.beans.*;
  49.  
  50. import java.applet.Applet;
  51.  
  52. import java.io.Serializable;
  53. import java.io.ObjectOutputStream;
  54. import java.io.ObjectInputStream;
  55. import java.io.IOException;
  56.  
  57. import java.awt.swing.border.*;
  58. import java.awt.swing.event.*;
  59. import java.awt.swing.plaf.*;
  60. import java.awt.accessibility.*;
  61.  
  62.  
  63. /**
  64.  * The base class for the Swing components. JComponent provides:
  65.  * <ul>
  66.  * <li>A "pluggable look and feel" (l&f) that can be specified by the
  67.  *     programmer or (optionally) selected by the user at runtime.
  68.  * <li>Components that are designed to be combined and extended in order 
  69.  *     to create custom components.
  70.  * <li>Comprehensive keystroke-handling that works with nested components.
  71.  * <li>Action objects, for single-point control of program actions initiated
  72.  *     by multiple components.
  73.  * <li>A border property that implicitly defines the component's insets.
  74.  * <li>The ability to set the preferred, minimim, and maximum size for a
  75.  *     component.
  76.  * <li>ToolTips -- short descriptions that pop up when the cursor lingers
  77.  *     over a component.
  78.  * <li>Autoscrolling -- automatic scrolling in a list, table, or tree that
  79.  *     occurs when the user is dragging the mouse.
  80.  * <li>Simple, easy dialog construction using static methods in the JOptionPane
  81.  *     class that let you display information and query the user.
  82.  * <li>Slow-motion graphics rendering using debugGraphics so you can see
  83.  *     what is being displayed on screen and whether or not it is being 
  84.  *     overwritten. 
  85.  * <li>Support for Accessibility.
  86.  * <li>Support for international Localization.
  87.  * </ul>
  88.  * <b><font size=+1>Keystroke Handling</font></b><br>
  89.  * The JComponent architecture makes it easy to handle keyboard events
  90.  * in nested components. You register interest in a particular combination
  91.  * of keystrokes by creating a KeyStroke object and registering it with the
  92.  * component. When you register the keystroke combination and its associated
  93.  * action, you also specify one of the following conditions to determine 
  94.  * when the action is initiated:
  95.  * <ul>
  96.  * <li>The component has the focus.
  97.  * <li>A child or grandchild of the component has the focus.<br>
  98.  *     You can use this capability to define global actions
  99.  *     for a composite component. For example, a tree control could
  100.  *     act on the Plus key to expand all elements in the tree, as long
  101.  *     as any component in the tree has the focus.
  102.  * <li>The window the component is in has the focus.<br>
  103.  *     In other words, if the component is a child or grandchild of
  104.  *     a window, and any component in that window has the focus, then
  105.  *     the component receives the event. You can use this 
  106.  *     capability to direct the keystroke combination Alt+C to the Cancel
  107.  *     button in a dialog, for example, as long any component in the dialog
  108.  *     has the focus.
  109.  * </ul>
  110.  * <b><font size=+1>Action objects</font></b><br>
  111.  * Action-interface objects provide a single point of control for program 
  112.  * actions. For example, a toolbar icon and a menu item can reference the 
  113.  * same Action object. When the Action object is disabled, the GUI items that 
  114.  * reference it are automatically disabled. The Action interface extends 
  115.  * ActionListener, specifying an enabled property as well as properties for 
  116.  * text-descriptions and graphic icons.  
  117.  * <p>
  118.  * <b><font size=+1>Compound Borders</font></b><br>
  119.  * Insets (the space between the edges of the component and the area
  120.  * it is drawn in) can be specified with a blank border. In addition, many
  121.  * border styles are available, which can be combined to create compound
  122.  * borders.
  123.  * <p>
  124.  * <b><font size=+1>Simple Dialog Construction</font></b><br>
  125.  * The JOptionPane class provides a variety of static methods that you
  126.  * can invoke to create and display both message dialogs and user-choice
  127.  * dialogs in a variety of formats. The "message" displayed in the
  128.  * dialog can be a string, a string-generating object, or an arbitrary
  129.  * component. You can also replace the choice-buttons with components 
  130.  * you specify for user-selections.
  131.  * <p>
  132.  * For example, the following line creates a simple message dialog that 
  133.  * requires the user's confirmation:
  134.  *   <pre>JOptionPane.showMessageDialog(null, "The file will be deleted.");</pre>
  135.  * Additional options are described  in the JOptionPane class.
  136.  * <p>
  137.  * <b><font size=+1>Support for Accessibility</font></b><br>
  138.  * Swing has built-in support for developers to make 
  139.  * products that are compatible with Assistive Technologies (for 
  140.  * alternative interfaces like, for example, braille.)  All of the Swing
  141.  * components implement interface Accessible.
  142.  * <p>
  143.  * Warning: serialized objects of this class will not be compatible with
  144.  * future swing releases.  The current serialization support is appropriate 
  145.  * for short term storage or RMI between Swing1.0 applications.  It will
  146.  * not be possible to load serialized Swing1.0 objects with future releases
  147.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  148.  * baseline for the serialized form of Swing objects.
  149.  *
  150.  * @see KeyStroke
  151.  * @see Action
  152.  * @see #setBorder
  153.  * @see #registerKeyboardAction
  154.  * @see JOptionPane
  155.  * @see #setDebugGraphicsOptions
  156.  * @see #setToolTipText
  157.  * @see #setAutoscrolls
  158.  *
  159.  * @version 2.53 03/04/98
  160.  * @author Hans Muller
  161.  * @author Arnaud Weber
  162.  */
  163. public abstract class JComponent extends Container implements Serializable
  164. {
  165.     /* The following fields support set methods for the corresponding
  166.      * java.awt.Component properties.  
  167.      */
  168.  
  169.     private Dimension preferredSize;
  170.     private Dimension minimumSize;
  171.     private Dimension maximumSize;
  172.     private Float alignmentX;
  173.     private Float alignmentY;
  174.     private AncestorNotifier ancestorNotifier;
  175.     Rectangle _bounds = new Rectangle();
  176.  
  177.  
  178.     /* Backing store for JComponent properties and listeners
  179.      */
  180.  
  181.     protected ComponentUI ui;
  182.     protected EventListenerList listenerList = new EventListenerList();
  183.     
  184.     private Hashtable clientProperties;
  185.     private VetoableChangeSupport vetoableChangeSupport;
  186.     private Autoscroller autoscroller;
  187.     private int flags;
  188.     private Border border;
  189.  
  190.     private transient Rectangle tmpRect;
  191.  
  192.  
  193.     /** 
  194.      * Constant used for registerKeyboardAction() which
  195.      * means that the command should be invoked when
  196.      * the component has the focus.
  197.      */
  198.     public static final int WHEN_FOCUSED = 0;
  199.  
  200.     /** 
  201.      * Constant used for registerKeyboardAction() which 
  202.      * means that the comand should be invoked when the receiving
  203.      * component is an ancestor of the focused component or is
  204.      * itself the focused component.
  205.      */
  206.     public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
  207.  
  208.     /**
  209.      * Constant used for registerKeyboardAction() which
  210.      * means that the command should be invoked when
  211.      * the receiving component is in the window that has the focus
  212.      * or is itself the focused component.
  213.      */
  214.     public static final int WHEN_IN_FOCUSED_WINDOW = 2;
  215.  
  216.     /** 
  217.      * Constant used by some of the apis to mean that no condition is defined.
  218.      */
  219.     public static final int UNDEFINED_CONDITION = -1;
  220.  
  221.     /**
  222.      * The key used by JComponent to access keyboard bindings.
  223.      */
  224.     private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
  225.  
  226.     /**
  227.      * The comment to display when the cursor is over the component,
  228.      * also known as a "value tip", "flyover help", or "flyover label".
  229.      */
  230.     public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
  231.  
  232.     private static final String NEXT_FOCUS = "nextFocus";
  233.  
  234.     /** Private flags **/
  235.     private static final int REQUEST_FOCUS_DISABLED = 0;
  236.     private static final int IS_DOUBLE_BUFFERED     = 1;
  237.     private static final int ANCESTOR_USING_BUFFER  = 2;
  238.     private static final int IS_PAINTING_TILE       = 3;
  239.     private static final int HAS_FOCUS              = 4;
  240.     private static final int IS_OPAQUE              = 5;
  241.  
  242.     static {
  243.         // REMIND: Kludge for JDK1.2beta3 -- use offscreen metrics
  244.          System.setProperty("java2d.offfm", "true");
  245.     }
  246.     /**
  247.      * Default JComponent constructor.  This constructor does
  248.      * no initialization beyond calling the Container constructor,
  249.      * e.g. the initial layout manager is null.
  250.      */
  251.     public JComponent() {
  252.         super();
  253.         enableEvents(AWTEvent.FOCUS_EVENT_MASK);
  254.     }
  255.  
  256.  
  257.     /**
  258.      * Resets the UI property to a value from the current look and feel.
  259.      * JComponent subclasses must override this method like this:
  260.      * <pre>
  261.      *   public void updateUI() {
  262.      *      setUI((SliderUI)UIManager.getUI(this);
  263.      *   }
  264.      *  </pre>
  265.      * 
  266.      * @see #setUI
  267.      * @see UIManager#getLookAndFeel
  268.      * @see UIManager#getUI
  269.      */
  270.     public void updateUI() {}
  271.  
  272.  
  273.     /**
  274.      * Set the look and feel delegate for this component.
  275.      * JComponent subclasses generally override this method
  276.      * to narrow the argument type, e.g. in JSlider:
  277.      * <pre>
  278.      * public void setUI(SliderUI newUI) {
  279.      *     super.setUI(newUI);
  280.      * }
  281.      *  </pre>
  282.      * <p>
  283.      * Additionaly JComponent subclasses must provide a getUI
  284.      * method that returns the correct type, e.g.
  285.      * <pre>
  286.      * public SliderUI getUI() {
  287.      *     return (SliderUI)ui;
  288.      * }
  289.      * </pre>
  290.      * 
  291.      * @see #updateUI
  292.      * @see UIManager#getLookAndFeel
  293.      * @see UIManager#getUI
  294.      */
  295.     protected void setUI(ComponentUI newUI) {
  296.         /* We do not check that the UI instance is different
  297.          * before allowing the switch in order to enable the
  298.          * same UI instance *with different default settings*
  299.          * to be installed. 
  300.          */
  301.         if (ui != null) {
  302.             ui.uninstallUI(this);
  303.         }
  304.         ComponentUI oldUI = ui;
  305.         ui = newUI;
  306.         if (ui != null) {
  307.             ui.installUI(this);
  308.         }
  309.         invalidate();
  310.         firePropertyChange("UI", oldUI, ui);
  311.     }
  312.  
  313.  
  314.     /**
  315.      * Return the UIDefaults key used to look up the name of the
  316.      * swing.plaf.ComponentUI class that defines the look and feel 
  317.      * for this component.  Most applications will never need to 
  318.      * call this method.  Subclasses of JComponent that support
  319.      * pluggable look and feel should override this method to 
  320.      * return the name of the ComponentUI subclass that defines 
  321.      * their look and feel.
  322.      * 
  323.      * @return The name of a ComponentUI subclass.
  324.      * @see UIDefaults#getUI
  325.      * @beaninfo
  326.      *      expert: true
  327.      * description: UIClassID
  328.      */
  329.     public String getUIClassID() {
  330.         return "not a pluggable look and feel class";
  331.     }
  332.  
  333.  
  334.     /**
  335.      * Returns the graphics object used to paint this component.
  336.      * If DebugGraphics is turned on we create a new DebugGraphics
  337.      * object if neccessary otherwise we just configure the 
  338.      * specified graphics objects foreground and font.
  339.      * 
  340.      * @return A Graphics object configured for this component
  341.      */
  342.     protected Graphics getComponentGraphics(Graphics g) {
  343.         Graphics componentGraphics = g;
  344.         if (ui != null) {
  345.             if ((DebugGraphics.debugComponentCount() != 0) &&
  346.                     (shouldDebugGraphics() != 0) && 
  347.                     !(g instanceof DebugGraphics)) {
  348.                 if(g instanceof SwingGraphics) {
  349.                     if(!(((SwingGraphics)g).subGraphics() instanceof DebugGraphics)) {
  350.                         componentGraphics = new DebugGraphics(((SwingGraphics)g).subGraphics(),this);
  351.                         componentGraphics = SwingGraphics.createSwingGraphics(componentGraphics);
  352.                     }
  353.                 } else {
  354.                     componentGraphics = new DebugGraphics(g,this);
  355.                 }
  356.             }
  357.         }
  358.         componentGraphics.setColor(getForeground());
  359.         componentGraphics.setFont(getFont());
  360.  
  361.         return componentGraphics;
  362.     }
  363.  
  364.  
  365.     /**
  366.      * If the UI delegate is non-null, call its paint
  367.      * method.  We pass the delegate a copy of the Graphics 
  368.      * object to protect the rest of the paint code from 
  369.      * irrevocable changes (e.g. Graphics.translate()). 
  370.      * 
  371.      * @see #paint
  372.      */
  373.     protected void paintComponent(Graphics g) {
  374.         if (ui != null) {
  375.             Graphics scratchGraphics = SwingGraphics.createSwingGraphics(g.create());
  376.             try {
  377.                 ui.update(scratchGraphics, this);
  378.             }
  379.             finally {
  380.                 scratchGraphics.dispose();
  381.             }
  382.         }
  383.     }
  384.  
  385.     /**
  386.      * Paint this component's children.
  387.      * If shouldUseBuffer is true, no component ancestor has a buffer and 
  388.      * the component children can use a buffer if they have one.
  389.      * Otherwise, one ancestor has a buffer currently in use and children
  390.      * should not use a buffer to paint.
  391.      * @see #paint
  392.      * @see java.awt.Container#paint
  393.      */
  394.     protected void paintChildren(Graphics g) {
  395.         boolean isJComponent;
  396.         boolean shouldRecycle = false;
  397.         SwingGraphics sg;
  398.  
  399.         if(g instanceof SwingGraphics) {
  400.             sg = (SwingGraphics)g;
  401.         } else {
  402.             sg = SwingGraphics.createSwingGraphics(g);
  403.             shouldRecycle = true;
  404.         }
  405.  
  406.         synchronized(getTreeLock()) {
  407.             for (int i = getComponentCount() - 1 ; i >= 0 ; i--) {
  408.                 Component comp = getComponent(i);
  409.                 if (comp != null && isLightweightComponent(comp) && (comp.isVisible() == true)) {
  410.                     Rectangle cr;
  411.                     isJComponent = (comp instanceof JComponent);
  412.                     
  413.                     if(isJComponent) {
  414.                         if(tmpRect == null) {
  415.                             tmpRect = new Rectangle();
  416.                         }
  417.                         cr = tmpRect;
  418.                         ((JComponent)comp).getBounds(cr);
  419.                     } else {
  420.                         cr = comp.getBounds();
  421.                     }
  422.  
  423.                     if (sg.isClipIntersecting(cr)) {
  424.                         Graphics cg = SwingGraphics.createGraphics(
  425.                             g, cr.x, cr.y, cr.width, cr.height);
  426.                         boolean shouldSetFlagBack = false;
  427.                         try {
  428.                             if(isJComponent) {
  429.                                 if(getFlag(ANCESTOR_USING_BUFFER)) {
  430.                                     ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,true);
  431.                                     shouldSetFlagBack = true;
  432.                                 }
  433.                                 if(getFlag(IS_PAINTING_TILE)) {
  434.                                     ((JComponent)comp).setFlag(IS_PAINTING_TILE,true);
  435.                                     shouldSetFlagBack = true;
  436.                                 }
  437.                                 ((JComponent)comp).paint(cg);
  438.                             } else {
  439.                                 comp.paint(cg);
  440.                             }
  441.                         } finally {
  442.                             cg.dispose();
  443.                             if(shouldSetFlagBack) {
  444.                                 ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,false);
  445.                                 ((JComponent)comp).setFlag(IS_PAINTING_TILE,false);
  446.                             }
  447.                         }
  448.                     }
  449.                 }
  450.            
  451.             }
  452.         }
  453.         if(shouldRecycle) {
  454.             sg.recycle();
  455.         }
  456.     }
  457.  
  458.     /**
  459.      * Paint the component's border.
  460.      * 
  461.      * @see #paint
  462.      * @see #setBorder
  463.      */
  464.     protected void paintBorder(Graphics g) {    
  465.         Border border = getBorder();
  466.         if (border != null) {
  467.             border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
  468.         }
  469.     }
  470.  
  471.  
  472.     /**
  473.      * Calls paint(g).  Doesn't clear the background but see 
  474.      * ComponentUI.update() which is called by paintComponent.
  475.      * 
  476.      * @see #paint
  477.      * @see #paintComponent
  478.      * @see java.awt.swing.plaf.ComponentUI
  479.      */
  480.     public void update(Graphics g) {
  481.         paint(g);
  482.     }
  483.  
  484.  
  485.     
  486.  
  487.     /**
  488.      * This method is invoked by Swing to draw components.
  489.      * Applications should not invoke paint directly, 
  490.      * but should instead use the <code>repaint</code> method to
  491.      * schedule the component for redrawing.
  492.      * <p>
  493.      * This method actually delegates the work of painting to three
  494.      * protected methods: <code>paintComponent</code>, <code>paintBorder</code>,
  495.      * and <code>paintChildren</code>.  They're called in the order
  496.      * listed to ensure that children appear on top of component itself.
  497.      * Generally speaking, the component and its children should not
  498.      * paint in the insets area allocated to the border. Subclasses can 
  499.      * just override this method, as always.  A subclass that just 
  500.      * wants to specialize the UI (look and feel) delegates paint 
  501.      * method should just override <code>paintComponent</code>.
  502.      * 
  503.      * @see #paintComponent
  504.      * @see #paintBorder
  505.      * @see #paintChildren
  506.      * @see #getComponentGraphics
  507.      * @see #repaint
  508.      */
  509.     public void paint(Graphics g) {
  510.         if (getWidth() == 0 || getHeight() == 0) {
  511.             return;
  512.         }
  513.         Graphics componentGraphics = getComponentGraphics(g);
  514.         boolean shouldRecycle;
  515.         if((componentGraphics instanceof SwingGraphics)) {
  516.             shouldRecycle = false;
  517.         } else {
  518.             shouldRecycle = true;
  519.         }
  520.         SwingGraphics co = SwingGraphics.createSwingGraphics(componentGraphics);
  521.         Image offscr = null;
  522.         RepaintManager repaintManager = RepaintManager.currentManager(this);
  523.         int clipX = co.getClipX();
  524.         int clipY = co.getClipY();
  525.         int clipW = co.getClipWidth();
  526.         int clipH = co.getClipHeight();
  527.  
  528.         if(clipW > getWidth()) {
  529.             clipW = getWidth();
  530.         }
  531.         if(clipH > getHeight()) {
  532.             clipH = getHeight();
  533.         }
  534.  
  535.         if(repaintManager.isDoubleBufferingEnabled() && 
  536.            !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) {
  537.             int bw,bh;
  538.             int x,y,maxx,maxy;
  539.             offscr = repaintManager.getOffscreenBuffer(this,clipW,clipH);
  540.  
  541.             if(shouldRecycle) {
  542.                 co.recycle();
  543.                 shouldRecycle = false;
  544.             }
  545.             co = SwingGraphics.createSwingGraphics(offscr.getGraphics());
  546.             co.translate(-clipX,-clipY);
  547.  
  548.             bw = offscr.getWidth(null);
  549.             bh = offscr.getHeight(null);
  550.  
  551.             if(bw > clipW) {
  552.                 bw = clipW;
  553.             }
  554.             if(bh > clipH) {
  555.                 bh = clipH;
  556.             }
  557.             try {
  558.                 setFlag(ANCESTOR_USING_BUFFER,true);
  559.                 setFlag(IS_PAINTING_TILE,true);
  560.                 for(x = 0, maxx = clipW; x < maxx ;  x += bw ) {
  561.                     for(y=0, maxy = clipH; y < maxy ; y += bh) {
  562.                         if((y+bh) >= maxy && (x+bw) >= maxx) 
  563.                             setFlag(IS_PAINTING_TILE,false);
  564.                         co.translate(-x,-y);
  565.                         co.setClip(clipX+x,clipY + y,bw,bh);
  566.                         if(!rectangleIsObscured(clipX,clipY,bw,bh)) {
  567.                             paintComponent(co);
  568.                             paintBorder(co);
  569.                         }
  570.                         paintChildren(co);
  571.                         g.drawImage(offscr,clipX + x,clipY + y,this);
  572.                         co.translate(x,y);
  573.                     }
  574.                 }
  575.             } finally {
  576.                 setFlag(ANCESTOR_USING_BUFFER,false);
  577.                 setFlag(IS_PAINTING_TILE,false);
  578.                 co.dispose();
  579.             }
  580.         } else {
  581.             if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
  582.                 paintComponent(co);
  583.                 paintBorder(co);
  584.             } 
  585.             paintChildren(co);
  586.         }
  587.         if(shouldRecycle) {
  588.             co.recycle();
  589.         }
  590.     }
  591.  
  592.     /**
  593.      *  Returns true if the receiving component is currently painting a tile.
  594.      *  If this method returns true, paint will be called again for another
  595.      *  tile. This method returns false if you are not painting a tile or
  596.      *  if the last tile is painted.
  597.      *  Use this method to keep some state you might need between tiles.
  598.      */
  599.     public boolean isPaintingTile() {
  600.         return getFlag(IS_PAINTING_TILE);
  601.     }
  602.     
  603.  
  604.     /** 
  605.      * Override this method and return true if your component is the root of
  606.      * of a component tree with its own focus cycle. 
  607.      */
  608.     public boolean isFocusCycleRoot() {
  609.         return false;
  610.     }
  611.  
  612.     /**
  613.      * Override this method and return true if your JComponent manages focus.
  614.      * If your component manages focus, the focus manager will handle your 
  615.      * component's children. All key event will be sent to your key listener
  616.      * including TAB and SHIFT+TAB. CONTROL + TAB and CONTROL + SHIFT + TAB
  617.      * will move the focus to the next / previous component.
  618.      */
  619.     public boolean isManagingFocus() {
  620.         return false;
  621.     }
  622.  
  623.     /**
  624.      * Specifies the next component to get the focus after this one,
  625.      * for example, when the tab key is pressed. Invoke this method
  626.      * to override the default focus-change sequence.
  627.      * @beaninfo
  628.      *      expert: true
  629.      * description: The next component to get focus after this one.
  630.      */
  631.     public void setNextFocusableComponent(Component aComponent) {
  632.         putClientProperty(NEXT_FOCUS,aComponent);
  633.     }
  634.  
  635.     /**
  636.      * Return the next focusable component or null if the focus manager
  637.      * should choose the next focusable component automatically
  638.      */
  639.     public Component getNextFocusableComponent() {
  640.         return (Component) getClientProperty(NEXT_FOCUS);
  641.     }
  642.  
  643.     /** 
  644.      *  Set whether the receiving component can obtain the focus by
  645.      *  calling requestFocus. The default value is true.
  646.      *  Note: Setting this property to false will not prevent the focus
  647.      *  manager from setting the focus to this component, it will prevent
  648.      *  the component from getting the focus when the focus is requested
  649.      *  explicitly. Override isFocusTraversable and return false if the
  650.      *  component should never get the focus.
  651.      * @beaninfo
  652.      *      expert: true
  653.      * description: Whether the component can obtain the focus by calling requestFocus.
  654.      */
  655.     public void setRequestFocusEnabled(boolean aFlag) {
  656.         setFlag(REQUEST_FOCUS_DISABLED,(aFlag ? false:true));
  657.     }
  658.  
  659.     /** Return whether the receiving component can obtain the focus by
  660.      *  calling requestFocus 
  661.      *  @see #setRequestFocusEnabled()
  662.      */
  663.     public boolean isRequestFocusEnabled() {
  664.         return (getFlag(REQUEST_FOCUS_DISABLED) ? false : true);
  665.     }
  666.  
  667.     /** Set focus on the receiving component if isRequestFocusEnabled returns true **/
  668.     public void requestFocus() {
  669.         if(isRequestFocusEnabled()) {
  670.             super.requestFocus();
  671.         }
  672.     }
  673.  
  674.     /** Set the focus on the receiving component. This method is for focus managers, you
  675.      *  rarely want to call this method, use requestFocus() enstead.
  676.      */
  677.     public void grabFocus() {
  678.         super.requestFocus();
  679.     }
  680.  
  681.     /**
  682.      * Set the preferred size of the receiving component.
  683.      * if <code>preferredSize</code> is null, the UI will
  684.      * be asked for the preferred size 
  685.      * @beaninfo
  686.      *   preferred: true
  687.      * description: The preferred size of the component.
  688.      */
  689.     public void setPreferredSize(Dimension preferredSize) {
  690.         this.preferredSize = preferredSize;
  691.     }
  692.  
  693.     /**
  694.      * If the preferredSize has been set to a non-null value
  695.      * just return it.  If the UI delegates getPreferredSize()
  696.      * method returns a non null then value return that, otherwise
  697.      * defer to the components layout manager.
  698.      *
  699.      * @return the value of the preferredSize property.
  700.      * @see #setPreferredSize
  701.      */
  702.     public Dimension getPreferredSize() {
  703.         if (preferredSize != null) {
  704.             return preferredSize;
  705.         }
  706.         Dimension size = null;
  707.         if (ui != null) {
  708.             size = ui.getPreferredSize(this);
  709.         }
  710.         return (size != null) ? size : super.getPreferredSize();
  711.     }
  712.  
  713.  
  714.     /**
  715.      * Sets the maximumSize of this component to a constant
  716.      * value.  Subsequent calls to getMaximumSize will always 
  717.      * return this value, the components UI will not be asked
  718.      * to compute it.  Setting the maximumSize to null
  719.      * restores the default behavior.
  720.      * 
  721.      * @see #getMaximumSize
  722.      * @beaninfo
  723.      *   preferred: true
  724.      * description: The maximum size of the component.
  725.      */
  726.     public void setMaximumSize(Dimension maximumSize) {
  727.         this.maximumSize = maximumSize;
  728.     }
  729.  
  730.     /**
  731.      * If the maximumSize has been set to a non-null value
  732.      * just return it.  If the UI delegates getMaximumSize()
  733.      * method returns a non null value then return that, otherwise
  734.      * defer to the components layout manager.
  735.      *
  736.      * @return the value of the maximumSize property.
  737.      * @see #setMaximumSize
  738.      */
  739.     public Dimension getMaximumSize() {
  740.         if (maximumSize != null) {
  741.             return maximumSize;
  742.         }
  743.         Dimension size = null;
  744.         if (ui != null) {
  745.             size = ui.getMaximumSize(this);
  746.         }
  747.         return (size != null) ? size : super.getMaximumSize();
  748.     }
  749.  
  750.  
  751.     /**
  752.      * Sets the minimumSize of this component to a constant
  753.      * value.  Subsequent calls to getMinimumSize will always 
  754.      * return this value, the components UI will not be asked
  755.      * to compute it.  Setting the minimumSize to null
  756.      * restores the default behavior.
  757.      * 
  758.      * @see #getMinimumSize
  759.      * @beaninfo
  760.      *   preferred: true
  761.      * description: The minimum size of the component.
  762.      */
  763.     public void setMinimumSize(Dimension minimumSize) {
  764.         this.minimumSize = minimumSize;
  765.     }
  766.  
  767.     /**
  768.      * If the minimumSize has been set to a non-null value
  769.      * just return it.  If the UI delegates getMinimumSize()
  770.      * method returns a non null value then return that, otherwise
  771.      * defer to the components layout manager.
  772.      *
  773.      * @return the value of the minimumSize property.
  774.      * @see #setMinimumSize
  775.      */
  776.     public Dimension getMinimumSize() {
  777.         if (minimumSize != null) {
  778.             return minimumSize;
  779.         }
  780.         Dimension size = null;
  781.         if (ui != null) {
  782.             size = ui.getMinimumSize(this);
  783.         }
  784.         return (size != null) ? size : super.getMinimumSize();
  785.     }
  786.  
  787.  
  788.     /**
  789.      * Give the UI delegate an opportunity to define the precise
  790.      * shape of this component for the sake of mouse processing.
  791.      *
  792.      * @return true if this component logically contains x,y.
  793.      * @see java.awt.Component#contains(int, int)
  794.      */
  795.     public boolean contains(int x, int y) {
  796.     return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
  797.     }
  798.  
  799.  
  800.     /**
  801.      * Sets the border of this component.  The Border object is
  802.      * responsible for defining the insets for the component
  803.      * (overriding any insets set directly on the component) and
  804.      * for optionally rendering any border decorations within the 
  805.      * bounds of those insets.  Borders should be used (rather
  806.      * than insets) for creating both decorative and non-decorative
  807.      * (e.g. margins and padding) regions for a swing component. 
  808.      * Compound borders can be used to nest multiple borders within a
  809.      * single component.
  810.      * <p>
  811.      * This is a bound property.
  812.      *
  813.      * @param border the border to be rendered for this component
  814.      * @see Border
  815.      * @see CompoundBorder
  816.      * @beaninfo
  817.      *       bound: true
  818.      *   preferred: true
  819.      * description: The component's border.
  820.      */
  821.     public void setBorder(Border border) {
  822.         Border         oldBorder = this.border;
  823.  
  824.         this.border = border;
  825.         firePropertyChange("border", oldBorder, border);
  826.         invalidate();
  827.     }
  828.  
  829.     /**
  830.      * Returns the border of this component or null if no border is
  831.      * currently set.
  832.      * 
  833.      * @return the border object for this component
  834.      * @see setBorder
  835.      */
  836.     public Border getBorder() {
  837.         return border;
  838.     }
  839.  
  840.     /**
  841.      * If a border has been set on this component, returns the
  842.      * border's insets, else calls super.getInsets.
  843.      *
  844.      * @return the value of the insets property.
  845.      * @see #setBorder
  846.      */
  847.     public Insets getInsets() {
  848.         if (border != null) {
  849.             return border.getBorderInsets(this);
  850.         }
  851.         return super.getInsets();
  852.     }
  853.  
  854.  
  855.     /**
  856.      * @return the value of the alignmentY property.
  857.      * @see #setAlignmentY
  858.      * @see java.awt.Component#getAlignmentY
  859.      */
  860.     public float getAlignmentY() {
  861.         return (alignmentY != null) ? alignmentY.floatValue() : super.getAlignmentY();
  862.     }
  863.  
  864.     /**
  865.      * Set the value of the alignmentY property.
  866.      * @see #getAlignmentY
  867.      * @beaninfo
  868.      *   preferred: true
  869.      * description: The preferred vertical alignment of the component
  870.      */
  871.     public void setAlignmentY(float alignmentY) {
  872.         this.alignmentY = new Float(alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY);
  873.     }
  874.  
  875.  
  876.     /**
  877.      * @return the value of the alignmentX property.
  878.      * @see #setAlignmentX
  879.      * @see java.awt.Component#getAlignmentX
  880.      */
  881.     public float getAlignmentX() {
  882.         return (alignmentX != null) ? alignmentX.floatValue() : super.getAlignmentX();
  883.     }
  884.  
  885.     /**
  886.      * Set the value of the alignmentX property.
  887.      * @see #getAlignmentX
  888.      * @beaninfo
  889.      *   preferred: true
  890.      * description: The preferred horizontal alignment of the component
  891.      */
  892.     public void setAlignmentX(float alignmentX) {
  893.         this.alignmentX = new Float(alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX);
  894.     }
  895.  
  896.     /**
  897.      * Returns this component's graphics context, which lets you draw
  898.      * on a component. Use this method get a Graphics object and 
  899.      * then invoke oeprations on that object to draw on the component.
  900.      */
  901.     public Graphics getGraphics() {
  902.         if (shouldDebugGraphics() != 0) {
  903.             DebugGraphics graphics = new DebugGraphics(super.getGraphics(),
  904.                                                        this);
  905.             return graphics;
  906.         }
  907.         return SwingGraphics.createSwingGraphics(super.getGraphics());
  908.     }
  909.  
  910.  
  911.     /** Enables or disables diagnostic information about every graphics
  912.       * operation performed within the component or one of its children. The
  913.       * value of <b>debugOptions</b> determines how the component should
  914.       * display this information:
  915.       * <ul>
  916.       * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
  917.       * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
  918.       * times.
  919.       * <li>DebugGraphics.BUFFERED_OPTION - creates an ExternalWindow that
  920.       * displays the operations performed on the View's offscreen buffer.
  921.       * </ul>
  922.       * <b>debug</b> is bitwise OR'd into the current value.
  923.       * DebugGraphics.NONE_OPTION disables debugging.
  924.       * A value of 0 causes no changes to the debugging options.
  925.       * @beaninfo
  926.       *   preferred: true
  927.       * description: Diagnostic options for graphics operations.
  928.       */
  929.     public void setDebugGraphicsOptions(int debugOptions) {
  930.         DebugGraphics.setDebugOptions(this, debugOptions);
  931.     }
  932.  
  933.     /** Returns the state of graphics debugging.
  934.       * @see #setDebugGraphicsOptions
  935.       */
  936.     public int getDebugGraphicsOptions() {
  937.         return DebugGraphics.getDebugOptions(this);
  938.     }
  939.  
  940.     /** 
  941.      * Returns <b>true</b> if debug information is enabled for this JComponent
  942.      * or one if its parents.
  943.      */
  944.     int shouldDebugGraphics() {
  945.         return DebugGraphics.shouldComponentDebug(this);
  946.     }
  947.  
  948.     /**
  949.      * Register a new keyboard action.
  950.      * <b>anAction</b> will be invoked if a key event matching <b>aKeyStroke</b> occurs
  951.      * and <b>aCondition</b> is verified. The KeyStroke object defines a
  952.      * particular combination of a keyboard key and one or more modifiers 
  953.      * (alt, shift, ctrl, meta).
  954.      * <p>
  955.      * The <b>aCommand</b> will be set in the delivered event if specified.
  956.      * <p>
  957.      * The Condition can be one of:
  958.      * <blockquote>
  959.      * <DL>
  960.      * <DT>WHEN_FOCUSED
  961.      * <DD>The action will be invoked only when the keystroke occurs
  962.      *     while the component has the focus.
  963.      * <DT>WHEN_IN_FOCUSED_WINDOW
  964.      * <DD>The action will be invoked when the keystroke occurs while 
  965.      *     the component has the focus or if the component is in the 
  966.      *     window that has the focus. Note that the component need not
  967.      *     be an immediate descendent of the window -- it can be 
  968.      *     anywhere in the window's containment hierarchy. In other
  969.      *     words, whenever <em>any</em> component in the window has the focus,
  970.      *     the action registered with this component is invoked.
  971.      * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
  972.      * <DD>The action will be invoked when the keystroke occurs while the
  973.      *     component has the focus or if the component is an ancestor of
  974.      *     the component that has the focus.
  975.      * </DL>
  976.      * </blockquote>
  977.      * <p>
  978.      * The combination of keystrokes and conditions lets you define high
  979.      * level (semantic) action events for a specified keystroke+modifier
  980.      * combination (using the KeyStroke class) and direct to a parent or
  981.      * child of a component that has the focus, or to the component itself.
  982.      * In other words, in any hierarchical structure of components, an
  983.      * arbitrary key-combination can be immediately directed to the
  984.      * appropriate component in the hierarchy, and cause a specific method
  985.      * to be invoked (usually by way of adapter objects). 
  986.      * <p>
  987.      * If an action has already been registered for the receiving
  988.      * container, with the same charCode and the same modifiers,
  989.      * <b>anAction</b> will replace the action.
  990.      *
  991.      * @see KeyStroke
  992.      */
  993.     public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {
  994.       Hashtable bindings;
  995.       boolean firstKeyboardAction = false;
  996.  
  997.       synchronized(this) {
  998.         bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  999.         if(bindings == null) {
  1000.           bindings = new Hashtable();
  1001.           putClientProperty(KEYBOARD_BINDINGS_KEY,bindings);
  1002.           firstKeyboardAction = true;
  1003.         }
  1004.       }
  1005.  
  1006.       synchronized(bindings) {
  1007.         bindings.put(aKeyStroke,new KeyboardBinding(anAction,aCommand,aKeyStroke,aCondition));
  1008.       }
  1009.  
  1010.       /* This is the first time a keyboard binding is added, let's order
  1011.        * keyboard events...
  1012.        * ALERT: we need to enable events. Adding a listener will not work since
  1013.        *        we want our listener to be after all other listeners.
  1014.        */
  1015.       if(firstKeyboardAction) {
  1016.         enableEvents(AWTEvent.KEY_EVENT_MASK);
  1017.       }
  1018.     }
  1019.  
  1020.     /**
  1021.      *  Calls registerKeyboardAction(ActionListener,String,KeyStroke,condition) with a null command.
  1022.      */
  1023.     public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) {
  1024.         registerKeyboardAction(anAction,null,aKeyStroke,aCondition);
  1025.     }
  1026.  
  1027.     private Hashtable keyboardBindings() {
  1028.         Hashtable bindings;
  1029.         synchronized(this) {
  1030.             bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1031.         }
  1032.         return bindings;
  1033.     }
  1034.  
  1035.     /** 
  1036.      * Unregister a keyboard action.
  1037.      * 
  1038.      * @see #registerKeyboardAction
  1039.      */
  1040.     public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
  1041.         Hashtable bindings = keyboardBindings();
  1042.  
  1043.         if(bindings == null)
  1044.             return;
  1045.         synchronized(bindings) {
  1046.             bindings.remove(aKeyStroke);
  1047.         }
  1048.  
  1049.         if(bindings.size() == 0) {
  1050.             /** ALERT. We need a way to disable keyboard events only if there is no
  1051.              *        keyboard listener.
  1052.              */
  1053.         }
  1054.     }
  1055.  
  1056.     /** 
  1057.      * Return the KeyStrokes that will initiate registered actions.
  1058.      *
  1059.      * @return an array of KeyStroke objects 
  1060.      * @see #registerKeyboardAction
  1061.      */
  1062.     public KeyStroke[] getRegisteredKeyStrokes() {
  1063.         Hashtable bindings = keyboardBindings();
  1064.         KeyStroke result[];
  1065.         int i;
  1066.         Enumeration keys;
  1067.  
  1068.         if(bindings == null) 
  1069.             return new KeyStroke[0];
  1070.         synchronized(bindings) {
  1071.             result = new KeyStroke[bindings.size()];
  1072.             i = 0;
  1073.             keys = bindings.keys();
  1074.             while(keys.hasMoreElements())
  1075.                 result[i++] = (KeyStroke) keys.nextElement();
  1076.         }
  1077.         return result;
  1078.     }
  1079.  
  1080.     /** 
  1081.      * Return the condition that determines whether a registered action 
  1082.      * occurs in response to the specified keystroke.
  1083.      *
  1084.      * @return the action-keystroke condition 
  1085.      * @see #registerKeyboardAction
  1086.      */
  1087.     public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
  1088.         Hashtable bindings = keyboardBindings();
  1089.         if(bindings == null)
  1090.             return UNDEFINED_CONDITION;
  1091.         synchronized(bindings) {
  1092.             KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1093.             if(kb != null) {
  1094.                 return kb.getCondition();
  1095.             }
  1096.         }
  1097.         return UNDEFINED_CONDITION;
  1098.     }
  1099.  
  1100.     /** 
  1101.      * Return the object that will perform the action registered for a 
  1102.      * given keystroke.
  1103.      *
  1104.      * @return the ActionListener object invoked when the keystroke occurs 
  1105.      * @see #registerKeyboardAction
  1106.      */
  1107.     public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) {
  1108.         Hashtable bindings = keyboardBindings();
  1109.  
  1110.         if(bindings == null)
  1111.             return null;
  1112.         synchronized(bindings) {
  1113.             KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1114.             if(kb != null) {
  1115.                 return kb.getAction();
  1116.             }
  1117.         }
  1118.         return null;
  1119.     }
  1120.  
  1121.  
  1122.  
  1123.     /** 
  1124.      * Unregister all keyboard actions
  1125.      * 
  1126.      * @see #registerKeyboardAction
  1127.      */
  1128.     public void resetKeyboardActions() {
  1129.       synchronized(this) {
  1130.           Hashtable bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1131.           if(bindings != null) {
  1132.               bindings.clear();
  1133.           }
  1134.       }
  1135.       /* ALERT. We need a way to disable keyboard events only if there is no
  1136.        *        keyboard listener.
  1137.        */
  1138.     }
  1139.  
  1140.     /** 
  1141.      * Request the focus for the component that should have the focus
  1142.      * by default. The default implementation will recursively request 
  1143.      * the focus on the first component that is focus-traversable.
  1144.      *
  1145.      * @return false if the focus has not been set, otherwise
  1146.      *         return true
  1147.      */
  1148.     public boolean requestDefaultFocus() {
  1149.         Component ca[] = getComponents();
  1150.         int i;
  1151.         for(i=0 ; i < ca.length ; i++) {
  1152.             if(ca[i].isFocusTraversable()) {
  1153.                 if(ca[i] instanceof JComponent) {
  1154.                     ((JComponent)ca[i]).grabFocus();
  1155.                 } else {
  1156.                     ca[i].requestFocus();
  1157.                 }
  1158.                 return true;
  1159.             }
  1160.             if(ca[i] instanceof JComponent && !((JComponent)ca[i]).isManagingFocus()) {
  1161.                 if(((JComponent)(ca[i])).requestDefaultFocus()) {
  1162.                     return true;
  1163.                 }
  1164.             } 
  1165.         }
  1166.         return false;
  1167.     }
  1168.     
  1169.     public void setVisible(boolean aFlag) {
  1170.     if(aFlag != isVisible()) {
  1171.         super.setVisible(aFlag);
  1172.         Container parent = getParent();
  1173.         if(parent != null) {
  1174.         Rectangle r = getBounds();
  1175.         parent.repaint(r.x,r.y,r.width,r.height);
  1176.         }
  1177.     }
  1178.     }
  1179.     
  1180.     /**
  1181.      * Identifies whether or not this component can receive the focus.
  1182.      * A disabled button, for example, would return false.
  1183.      *
  1184.      * @return true if this component can receive the focus
  1185.      */
  1186.     public boolean isFocusTraversable() {
  1187.       boolean result = false;
  1188.       Hashtable bindings;
  1189.  
  1190.       synchronized(this) {
  1191.         bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1192.       }
  1193.       if(bindings != null) {
  1194.         synchronized(bindings) {
  1195.             Enumeration keys = bindings.keys();
  1196.             KeyboardBinding b;
  1197.  
  1198.             while(keys.hasMoreElements()) {
  1199.                 b = (KeyboardBinding) bindings.get(keys.nextElement());
  1200.                 if(b.getCondition() == WHEN_FOCUSED) {
  1201.                     result = true;
  1202.                     break;
  1203.                 }
  1204.             }
  1205.         }
  1206.       }
  1207.       return result;
  1208.     }
  1209.  
  1210.     protected void processFocusEvent(FocusEvent e) {
  1211.         switch(e.getID()) {
  1212.           case FocusEvent.FOCUS_GAINED:
  1213.               setFlag(HAS_FOCUS, true);
  1214.               break;
  1215.           case FocusEvent.FOCUS_LOST:
  1216.               setFlag(HAS_FOCUS, false);
  1217.               break;
  1218.         }
  1219.  
  1220.         // Call super *after* setting flag, in case listener calls paint.
  1221.         super.processFocusEvent(e);
  1222.     }
  1223.  
  1224.     /**
  1225.      * Process any key events that the component itself 
  1226.      * recognizes.  This will be called after the focus
  1227.      * manager and any interested listeners have been
  1228.      * given a chance to steal away the event.  This 
  1229.      * method will only be called is the event has not
  1230.      * yet been consumed.  This method is called prior
  1231.      * to the keyboard UI logic.
  1232.      * <p>
  1233.      * This is implemented to do nothing.  Subclasses would
  1234.      * normally override this method if they process some
  1235.      * key events themselves.  If the event is processed,
  1236.      * it should be consumed.
  1237.      */
  1238.     protected void processComponentKeyEvent(KeyEvent e) {
  1239.     }
  1240.  
  1241.     /** Override processKeyEvent to process events **/
  1242.     protected void processKeyEvent(KeyEvent e) {
  1243.       // focus manager gets to steal the event if it wants it.
  1244.       boolean result;
  1245.       boolean shouldProcessKey = false;
  1246.       if(FocusManager.isFocusManagerEnabled()) {
  1247.           FocusManager focusManager = FocusManager.getCurrentManager();
  1248.           focusManager.processKeyEvent(this,e);
  1249.           if(e.isConsumed()) {
  1250.               return;
  1251.           }
  1252.       }
  1253.  
  1254.       // This gives the key event listeners a crack at the event
  1255.       super.processKeyEvent(e);
  1256.  
  1257.       // give the component itself a crack at the event
  1258.       if (! e.isConsumed()) {
  1259.       processComponentKeyEvent(e);
  1260.       }
  1261.  
  1262.       if(e.getID() == KeyEvent.KEY_PRESSED) {
  1263.           shouldProcessKey = true;
  1264.           if(!KeyboardState.keyIsPressed(e.getKeyCode()))
  1265.               KeyboardState.registerKeyPressed(e.getKeyCode());
  1266.       } else if(e.getID() == KeyEvent.KEY_RELEASED) {
  1267.           if(KeyboardState.keyIsPressed(e.getKeyCode())) {
  1268.               shouldProcessKey = true;
  1269.               KeyboardState.registerKeyReleased(e.getKeyCode());
  1270.           }
  1271.       } else if(e.getID() == KeyEvent.KEY_TYPED) {
  1272.           shouldProcessKey = true;
  1273.       }
  1274.  
  1275.       if(e.isConsumed()) {
  1276.         return;
  1277.       }
  1278.  
  1279.       if(shouldProcessKey && e.getID() == KeyEvent.KEY_PRESSED) {
  1280.         result = processKeyBindings(e,true);
  1281.         if(result)
  1282.           e.consume();
  1283.       } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_RELEASED) {
  1284.           result = processKeyBindings(e,false);
  1285.           if(result) {
  1286.               e.consume();
  1287.           }
  1288.       } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_TYPED) {
  1289.           result = processKeyBindings(e,false);
  1290.           if(result) {
  1291.               e.consume();
  1292.           }
  1293.       }
  1294.     }
  1295.  
  1296.     KeyboardBinding bindingForKeyStroke(KeyStroke ks,int condition) {
  1297.         Hashtable bindings;
  1298.         KeyboardBinding b;
  1299.         KeyboardBinding result = null;
  1300.  
  1301.         synchronized(this) {
  1302.             bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1303.         }
  1304.         if(bindings != null) {
  1305.             synchronized(bindings) {
  1306.                 b = (KeyboardBinding) bindings.get(ks);
  1307.                 //                System.out.println("Bindings are " + bindings);
  1308.                 if(b != null) {
  1309.                     ActionListener action = b.getAction();
  1310.                     if((action instanceof Action) && !(((Action)action).isEnabled()))
  1311.                         action = null;
  1312.                     if(action != null) {
  1313.                         switch(b.getCondition()) {
  1314.                         case WHEN_FOCUSED:
  1315.                             if(condition == WHEN_FOCUSED)
  1316.                                 result = b;
  1317.                             break;
  1318.                         case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
  1319.                             if(condition == WHEN_FOCUSED ||
  1320.                                condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
  1321.                                 result = b;
  1322.                             break;
  1323.                         case WHEN_IN_FOCUSED_WINDOW:
  1324.                             if(condition == WHEN_FOCUSED ||
  1325.                                condition == WHEN_IN_FOCUSED_WINDOW ||
  1326.                                condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
  1327.                                 result = b;
  1328.                             break;
  1329.                         }
  1330.                     }
  1331.                 }
  1332.             }
  1333.         }
  1334.         return result;
  1335.     }
  1336.  
  1337.     boolean processKeyBinding(KeyEvent e,int condition,boolean pressed) {
  1338.         Hashtable bindings;
  1339.         int i,c;
  1340.         boolean onKeyRelease = (pressed?false:true);
  1341.         KeyboardBinding binding = null;
  1342.         KeyStroke ks;
  1343.  
  1344.     if(isEnabled()) {
  1345.         if(e.getID() == KeyEvent.KEY_TYPED) {
  1346.         binding = bindingForKeyStroke((ks=KeyStroke.getKeyStroke(e.getKeyChar())),condition);
  1347.         } else {
  1348.         binding = bindingForKeyStroke((ks=KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(),
  1349.                                      onKeyRelease)), condition);
  1350.         }
  1351.         //System.out.println("e=" + e + "ks is " + ks);
  1352.         if(binding != null) {
  1353.         ActionListener listener = binding.getAction();
  1354.         if(listener != null) {
  1355.             listener.actionPerformed(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,binding.getCommand()));
  1356.             return true;
  1357.         }
  1358.         }
  1359.     }
  1360.     
  1361.     return false;
  1362.     }
  1363.  
  1364.     boolean processKeyBindings(KeyEvent e,boolean pressed) {
  1365.       Container parent;
  1366.       Vector    processedComponents = new Vector();
  1367.  
  1368.       /* Do we have a key binding for e? */
  1369.       if(processKeyBinding(e,WHEN_FOCUSED,pressed))
  1370.         return true;
  1371.  
  1372.       processedComponents.addElement(this);
  1373.  
  1374.       /* We have no key binding. Let's try the path from our parent to the window excluded
  1375.        * We store the path components so we can avoid asking the same component twice.
  1376.        */
  1377.       //System.out.println("parent of focus");
  1378.       parent = this.getParent();
  1379.       while(parent != null && !(parent instanceof Window) && 
  1380.             !(parent instanceof Applet)) {
  1381.         if(parent instanceof JComponent) {
  1382.           if(((JComponent)parent).processKeyBinding(e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,pressed))
  1383.             return true;
  1384.           processedComponents.addElement(parent);
  1385.         }
  1386.         parent = parent.getParent();
  1387.       }
  1388.  
  1389.       /* No components between the focused component and the window is actually interested
  1390.        * by the key event. Let's try the other JComponent in this window.
  1391.        */
  1392.       //System.out.println("the rest");
  1393.       if(parent != null) {
  1394.         return JComponent.processKeyBindingsForAllComponents(e,parent,processedComponents,pressed);
  1395.       }
  1396.       return false;
  1397.     }
  1398.  
  1399.     static boolean processKeyBindingsForAllComponents(KeyEvent e,Container container,Vector alreadyProcessed,
  1400.                                                       boolean pressed) {
  1401.       int i;
  1402.       Component subComponents[];
  1403.  
  1404.       if(container instanceof JComponent && !alreadyProcessed.contains(container)) {
  1405.         if(((JComponent)container).processKeyBinding(e,WHEN_IN_FOCUSED_WINDOW,pressed))
  1406.           return true;
  1407.       }
  1408.  
  1409.       subComponents = container.getComponents();
  1410.       for(i=0 ; i < subComponents.length ; i++) {
  1411.         if(subComponents[i] instanceof Container) {
  1412.           if(processKeyBindingsForAllComponents(e,(Container)subComponents[i],alreadyProcessed,pressed))
  1413.             return true;
  1414.         }
  1415.       }
  1416.       return false;
  1417.     }
  1418.  
  1419.     /**
  1420.      * Registers the text to display in a tool tip. 
  1421.      * The text displays when the cursor lingers over the component.
  1422.      * <p>
  1423.      * See <a href="http://java.sun.com/docs/books/tutorial/ui/swing/tooltip.html">How to Use Tool Tips</a>
  1424.      * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
  1425.      * for further documentation.
  1426.      *
  1427.      * @param text  The string to display. If the text is null, 
  1428.      *              the tool tip is turned off for this component.
  1429.      * @see #TOOL_TIP_TEXT_KEY
  1430.      * @beaninfo
  1431.      *   preferred: true
  1432.      * description: The text to display in a tool tip.
  1433.      */
  1434.     public void setToolTipText(String text) {
  1435.         putClientProperty(TOOL_TIP_TEXT_KEY, text);
  1436.         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
  1437.         if (text != null) {
  1438.             toolTipManager.registerComponent(this);
  1439.         } else {
  1440.             toolTipManager.unregisterComponent(this);
  1441.         }
  1442.     }
  1443.  
  1444.     /**
  1445.      * Return the tooltip string that has been set with setToolTipText()
  1446.      *
  1447.      * @return the text of the tool tip
  1448.      * @see #TOOL_TIP_TEXT_KEY
  1449.      */
  1450.     public String getToolTipText() {
  1451.         return (String)getClientProperty(TOOL_TIP_TEXT_KEY);        
  1452.     }
  1453.  
  1454.  
  1455.     /**
  1456.      * Returns the string to be used as the tooltip for <i>event</i>.  By default
  1457.      * this returns any string set using setToolTipText().  If a component provides
  1458.      * more extensize API to support differing tooltips at different locations,
  1459.      * this method should be overridden.
  1460.      */
  1461.     public String getToolTipText(MouseEvent event) {
  1462.         return getToolTipText();
  1463.     }
  1464.  
  1465.     /**
  1466.      * Return the tooltip location in the receiving component coordinate system
  1467.      * If null is returned, Swing will choose a location. 
  1468.      * The default implementation returns null.
  1469.      * <code>event</event> is the MouseEvent that caused the ToolTipManager to 
  1470.      * show the tooltip. 
  1471.      */
  1472.     public Point getToolTipLocation(MouseEvent event) {
  1473.         return null;
  1474.     }
  1475.  
  1476.  
  1477.     /**
  1478.      * Returns the instance of JToolTip that should be used to display the tooltip.
  1479.      * Components typically would not override this method, but it can be used to
  1480.      * cause different tooltips to be displayed differently.
  1481.      */
  1482.     public JToolTip createToolTip() {
  1483.         JToolTip tip = new JToolTip();
  1484.         tip.setComponent(this);
  1485.         return tip;
  1486.     }
  1487.  
  1488.     /**
  1489.      * Forwards the <b>scrollRectToVisible()</b> message to the JComponent's
  1490.      * parent. Components that can service the request, such as a JViewport,
  1491.      * override this method and perform the scrolling.
  1492.      *
  1493.      * @see JViewport
  1494.      */
  1495.     public void scrollRectToVisible(Rectangle aRect) {
  1496.         Container parent;
  1497.         int dx = getX(), dy = getY();
  1498.  
  1499.         for (parent = getParent();
  1500.              parent != null && !(parent instanceof JComponent);
  1501.              parent = parent.getParent()) {
  1502.              Rectangle bounds = parent.getBounds();
  1503.  
  1504.              dx += bounds.x;
  1505.              dy += bounds.y;
  1506.         }
  1507.  
  1508.         if (parent != null) {
  1509.             aRect.x += dx;
  1510.             aRect.y += dy;
  1511.             ((JComponent)parent).scrollRectToVisible(aRect);
  1512.             aRect.x -= dx;
  1513.             aRect.y -= dy;
  1514.         }
  1515.     }
  1516.  
  1517.     /**
  1518.      * If <i>true</i> this component will automatically scroll its contents when
  1519.      * dragged, if contained in a component that supports scrolling, such as
  1520.      * JViewport
  1521.      *
  1522.      * @see JViewport
  1523.      * @see #getAutoscrolls
  1524.      *
  1525.      * @beaninfo
  1526.      *      expert: true
  1527.      * description: Whether this component automatically scrolls its contents when dragged. 
  1528.      */
  1529.     public void setAutoscrolls(boolean autoscrolls) {
  1530.         if (autoscrolls) {
  1531.             if (autoscroller == null) {
  1532.                 autoscroller = new Autoscroller(this);
  1533.             }
  1534.         } else {
  1535.             if (autoscroller != null) {
  1536.                 autoscroller.stop();
  1537.                 autoscroller = null;
  1538.             }
  1539.         }
  1540.     }
  1541.  
  1542.     /**
  1543.      * Returns <i>true</i> if this component automatically scrolls its 
  1544.      * contents when dragged, (when contained in a component that supports 
  1545.      * scrolling, like JViewport
  1546.      *
  1547.      * @see JViewport
  1548.      * @see #setAutoscrolls
  1549.      */
  1550.     public boolean getAutoscrolls() {
  1551.         return autoscroller != null;
  1552.     }
  1553.  
  1554.     protected void processMouseMotionEvent(MouseEvent e) {
  1555.         boolean dispatch = true;
  1556.         if (autoscroller != null) {
  1557.             if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
  1558.                 // We don't want to do the drags when the mouse moves if we're
  1559.                 // autoscrolling.  It makes it feel spastic.
  1560.                 dispatch = !autoscroller.timer.isRunning();
  1561.                 autoscroller.mouseDragged(e);
  1562.             }
  1563.         }
  1564.         if (dispatch) {
  1565.             super.processMouseMotionEvent(e);
  1566.         }
  1567.     }
  1568.  
  1569.     // Inner classes can't get at this method from a super class
  1570.     void superProcessMouseMotionEvent(MouseEvent e) {
  1571.         super.processMouseMotionEvent(e);
  1572.     }
  1573.  
  1574.     static class KeyboardBinding implements Serializable {
  1575.         ActionListener   action;
  1576.         String           command;
  1577.         KeyStroke keyStroke;
  1578.         int        condition;
  1579.  
  1580.         KeyboardBinding(ActionListener action,String aCommand,KeyStroke aKeyStroke,int condition) {
  1581.             this.action     = action;
  1582.             this.command    = aCommand;
  1583.             this.keyStroke  = aKeyStroke;
  1584.             this.condition  = condition;
  1585.         }
  1586.  
  1587.         ActionListener getAction() {
  1588.             return action;
  1589.         }
  1590.  
  1591.         String getCommand() {
  1592.             return command;
  1593.         }
  1594.  
  1595.         KeyStroke getKeyStroke() {
  1596.             return keyStroke;
  1597.         }
  1598.  
  1599.         int getCondition() {
  1600.             return condition;
  1601.         }
  1602.  
  1603.         public String toString() {
  1604.             return "KeyBinding ("+action+","+keyStroke+","+condition+")";
  1605.         }
  1606.     }
  1607.  
  1608.     // This class is used by the KeyboardState class to provide a single
  1609.     // instance which can be stored in the AppContext.
  1610.     static final class IntVector {
  1611.         int array[] = null;
  1612.         int count = 0;
  1613.         int capacity = 0;
  1614.  
  1615.         int size() {
  1616.             return count;
  1617.         }
  1618.  
  1619.         int elementAt(int index) {
  1620.             return array[index];
  1621.         }
  1622.  
  1623.         void addElement(int value) {
  1624.             if (count == capacity) {
  1625.                 capacity = (capacity + 2) * 2;
  1626.                 int[] newarray = new int[capacity];
  1627.                 if (count > 0) {
  1628.                     System.arraycopy(array, 0, newarray, 0, count);
  1629.                 }
  1630.                 array = newarray;
  1631.             }
  1632.             array[count++] = value;
  1633.         }
  1634.  
  1635.         void setElementAt(int value, int index) {
  1636.             array[index] = value;
  1637.         }
  1638.     }
  1639.  
  1640.     static class KeyboardState implements Serializable {
  1641.         private static final Object keyCodesKey = 
  1642.             JComponent.KeyboardState.class;
  1643.  
  1644.         // Get the array of key codes from the AppContext.
  1645.         static IntVector getKeyCodeArray() {
  1646.             IntVector iv = 
  1647.                 (IntVector)SwingUtilities.appContextGet(keyCodesKey);
  1648.             if (iv == null) {
  1649.                 iv = new IntVector();
  1650.                 SwingUtilities.appContextPut(keyCodesKey, iv);
  1651.             }
  1652.             return iv;
  1653.         }
  1654.  
  1655.         static void registerKeyPressed(int keyCode) {
  1656.             IntVector kca = getKeyCodeArray();
  1657.             int count = kca.size();
  1658.             int i;
  1659.             for(i=0;i<count;i++) {
  1660.                 if(kca.elementAt(i) == -1){
  1661.                     kca.setElementAt(keyCode, i);
  1662.                     return;
  1663.                 }
  1664.             }
  1665.             kca.addElement(keyCode);
  1666.         }
  1667.  
  1668.         static void registerKeyReleased(int keyCode) {
  1669.             IntVector kca = getKeyCodeArray();
  1670.             int count = kca.size();
  1671.             int i;
  1672.             for(i=0;i<count;i++) {
  1673.                 if(kca.elementAt(i) == keyCode) {
  1674.                     kca.setElementAt(-1, i);
  1675.                     return;
  1676.                 }
  1677.             }
  1678.         }
  1679.  
  1680.         static boolean keyIsPressed(int keyCode) {
  1681.             IntVector kca = getKeyCodeArray();
  1682.             int count = kca.size();
  1683.             int i;
  1684.             for(i=0;i<count;i++) {
  1685.                 if(kca.elementAt(i) == keyCode) {
  1686.                     return true;
  1687.                 }
  1688.             }
  1689.             return false;
  1690.         }
  1691.     }
  1692.  
  1693.  
  1694.     /**
  1695.      * --- Accessibility Support ---
  1696.      *
  1697.      *  JComponent will contain all of the methods in interface Accessible,
  1698.      *  though it won't actally implement the interface - that will be up
  1699.      *  to the individual objects which extend JComponent.
  1700.      */
  1701.  
  1702.     protected AccessibleContext accessibleContext = null;
  1703.  
  1704.     /**
  1705.      * Get the AccessibleContext associated with this JComponent
  1706.      *
  1707.      * @return the AccessibleContext of this JComponent
  1708.      */
  1709.     public AccessibleContext getAccessibleContext() {
  1710.         return accessibleContext;
  1711.     }
  1712.  
  1713.     /**
  1714.      * Inner class of JComponent used to provide default support for
  1715.      * accessibility.  This class is not meant to be used directly by
  1716.      * application developers, but is instead meant only to be 
  1717.      * subclassed by component developers.  Due to a restriction that 
  1718.      * protected inner classes cannot be subclassed outside of a 
  1719.      * package, this inner class has been made public.  When this 
  1720.      * restriction is lifted for JDK1.1.6, this class will be made
  1721.      * protected.
  1722.      * The class used to obtain the accessible role for this object.
  1723.      * <p>
  1724.      * Warning: serialized objects of this class will not be compatible with
  1725.      * future swing releases.  The current serialization support is appropriate
  1726.      * for short term storage or RMI between Swing1.0 applications.  It will
  1727.      * not be possible to load serialized Swing1.0 objects with future releases
  1728.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1729.      * baseline for the serialized form of Swing objects.
  1730.      */
  1731.     public abstract class AccessibleJComponent extends AccessibleContext
  1732.         implements Serializable, AccessibleComponent {
  1733.  
  1734.         // AccessibleContext methods
  1735.         //
  1736.         /**
  1737.          * Get the accessible name of this object.  This should almost never
  1738.          * return java.awt.Component.getName(), as that generally isn't
  1739.          * a localized name, and doesn't have meaning for the user.  If the
  1740.          * object is fundamentally a text object (e.g. a menu item), the
  1741.          * accessible name should be the text of the object (e.g. "save").
  1742.          * If the object has a tooltip, the tooltip text may also be an
  1743.          * appropriate String to return.
  1744.          *
  1745.          * @return the localized name of the object -- can be null if this 
  1746.          * object does not have a name
  1747.          * @see #setAccessibleName
  1748.          */
  1749.         public String getAccessibleName() {
  1750.             if (accessibleName != null) {
  1751.                 return accessibleName;
  1752.             } else {
  1753.                 Border border = getBorder();
  1754.                 if ((border != null) &&
  1755.                     (border instanceof TitledBorder)) {
  1756.                     return ((TitledBorder) border).getTitle();
  1757.                 }
  1758.             }
  1759.             return null;
  1760.         }
  1761.  
  1762.         /**
  1763.          * Get the accessible description of this object.  This should be
  1764.          * a concise, localized description of what this object is - what
  1765.          * is it's meaning to the user.  If the object has a tooltip, the
  1766.          * tooltip text may be an appropriate string to return, assuming
  1767.          * it contains a concise description of the object (instead of just
  1768.          * the name of the object - e.g. a "Save" icon on a toolbar that
  1769.          * had "save" as the tooltip text shouldn't return the tooltip
  1770.          * text as the description, but something like "Saves the current
  1771.          * text document" instead).
  1772.          *
  1773.          * @return the localized description of the object -- can be null if 
  1774.          * this object does not have a description
  1775.          * @see #setAccessibleDescription
  1776.          */
  1777.         public String getAccessibleDescription() {
  1778.             if (accessibleDescription != null) {
  1779.                 return accessibleDescription;
  1780.             } else {
  1781.                 try {
  1782.                     String ttt = getToolTipText(null);
  1783.                     if (ttt != null) {
  1784.                         return ttt;
  1785.                     }
  1786.                 } catch (Exception e) {
  1787.                     // Just in case the subclass overrode the
  1788.                     // getToolTipText method and actually 
  1789.                     // requires a MouseEvent.
  1790.                     // [[[FIXME:  WDW - we probably should require this
  1791.                     // method to take a MouseEvent and just pass it on
  1792.                     // to getToolTipText.  The swing-feedback traffic
  1793.                     // leads me to believe getToolTipText might change,
  1794.                     // though, so I was hesitant to make this change at
  1795.                     // this time.]]]          
  1796.                 }
  1797.             }
  1798.             return null;
  1799.         }
  1800.  
  1801.         /**
  1802.          * Get the role of this object.
  1803.          *
  1804.          * @return an instance of AccessibleRole describing the role of the 
  1805.          * object
  1806.          * @see AccessibleRole
  1807.          */
  1808.         public AccessibleRole getAccessibleRole() {
  1809.             return AccessibleRole.SWING_COMPONENT;
  1810.         }
  1811.  
  1812.         /**
  1813.          * Get the state of this object.
  1814.          *
  1815.          * @return an instance of AccessibleStateSet containing the current 
  1816.          * state set of the object
  1817.          * @see AccessibleState
  1818.          */
  1819.         public AccessibleStateSet getAccessibleStateSet() {
  1820.             return SwingUtilities.getAccessibleStateSet(JComponent.this);
  1821.         }
  1822.  
  1823.         /**
  1824.          * Get the Accessible parent of this object.  If the parent of this
  1825.          * object implements Accessible, this method should simply return
  1826.          * getParent().
  1827.          *
  1828.          * @return the Accessible parent of this object -- can be null if this
  1829.          * object does not have an Accessible parent
  1830.          */
  1831.         public Accessible getAccessibleParent() {
  1832.             if (accessibleParent != null) {
  1833.                 return accessibleParent;
  1834.             } else {
  1835.                 Container parent = getParent();
  1836.                 if (parent instanceof Accessible) {
  1837.                     return (Accessible) parent;
  1838.                 }
  1839.             }
  1840.             return null;
  1841.         }
  1842.  
  1843.         /**
  1844.          * Get the index of this object in its accessible parent. 
  1845.          *
  1846.          * @return the index of this object in its parent; -1 if this 
  1847.          * object does not have an accessible parent.
  1848.          * @see #getAccessibleParent
  1849.          */
  1850.         public int getAccessibleIndexInParent() {
  1851.             return SwingUtilities.getAccessibleIndexInParent(JComponent.this);
  1852.         }
  1853.  
  1854.         /**
  1855.          * Returns the number of accessible children in the object.  If all
  1856.          * of the children of this object implement Accessible, than this
  1857.          * method should return the number of children of this object.
  1858.          *
  1859.          * @return the number of accessible children in the object.
  1860.          */
  1861.         public int getAccessibleChildrenCount() {
  1862.             return SwingUtilities.getAccessibleChildrenCount(JComponent.this);
  1863.         }
  1864.  
  1865.         /**
  1866.          * Return the nth Accessible child of the object.  
  1867.          *
  1868.          * @param i zero-based index of child
  1869.          * @return the nth Accessible child of the object
  1870.          */
  1871.         public Accessible getAccessibleChild(int i) {
  1872.             return SwingUtilities.getAccessibleChild(JComponent.this,i);
  1873.         }
  1874.  
  1875.  
  1876.         /**
  1877.          * Return the locale of this object.
  1878.          *
  1879.          * @return the locale of this object
  1880.          */
  1881.         public Locale getLocale() {
  1882.             return JComponent.this.getLocale();
  1883.         }
  1884.  
  1885.         /**
  1886.          * Get the AccessibleComponent associated with this object if one
  1887.          * exists.  Otherwise return null.
  1888.          */
  1889.         public AccessibleComponent getAccessibleComponent() {
  1890.             return this;
  1891.         }
  1892.  
  1893.  
  1894.         // AccessibleComponent methods
  1895.         //
  1896.         /**
  1897.          * Get the background color of this object.
  1898.          *
  1899.          * @return the background color, if supported, of the object; 
  1900.          * otherwise, null
  1901.          */
  1902.         public Color getBackground() {
  1903.             return JComponent.this.getBackground();
  1904.         }
  1905.  
  1906.         /**
  1907.          * Set the background color of this object.
  1908.          * (For transparency, see <code>isOpaque</code>.)
  1909.          *
  1910.          * @param c the new Color for the background
  1911.          * @see #isOpaque
  1912.          */
  1913.         public void setBackground(Color c) {
  1914.             JComponent.this.setBackground(c);
  1915.         }
  1916.  
  1917.         /**
  1918.          * Get the foreground color of this object.
  1919.          *
  1920.          * @return the foreground color, if supported, of the object; 
  1921.          * otherwise, null
  1922.          */
  1923.         public Color getForeground() {
  1924.             return JComponent.this.getForeground();
  1925.         }
  1926.  
  1927.         /**
  1928.          * Set the foreground color of this object.
  1929.          *
  1930.          * @param c the new Color for the foreground
  1931.          */
  1932.         public void setForeground(Color c) {
  1933.             JComponent.this.setForeground(c);
  1934.         }
  1935.  
  1936.         /**
  1937.          * Get the Cursor of this object.
  1938.          *
  1939.          * @return the Cursor, if supported, of the object; otherwise, null
  1940.          */
  1941.         public Cursor getCursor() {
  1942.             return JComponent.this.getCursor();
  1943.         }
  1944.  
  1945.         /**
  1946.          * Set the Cursor of this object.
  1947.          *
  1948.          * @param c the new Cursor for the object
  1949.          */
  1950.         public void setCursor(Cursor cursor) {
  1951.             JComponent.this.setCursor(cursor);
  1952.         }
  1953.  
  1954.         /**
  1955.          * Get the Font of this object.
  1956.          *
  1957.          * @return the Font,if supported, for the object; otherwise, null
  1958.          */
  1959.         public Font getFont() {
  1960.             return JComponent.this.getFont();
  1961.         }
  1962.  
  1963.         /**
  1964.          * Set the Font of this object.
  1965.          *
  1966.          * @param f the new Font for the object
  1967.          */
  1968.         public void setFont(Font f) {
  1969.             JComponent.this.setFont(f);
  1970.         }
  1971.  
  1972.         /**
  1973.          * Get the FontMetrics of this object.
  1974.          *
  1975.          * @param f the Font
  1976.          * @return the FontMetrics, if supported, the object; otherwise, null
  1977.          * @see getFont
  1978.          */
  1979.         public FontMetrics getFontMetrics(Font f) {
  1980.             return JComponent.this.getFontMetrics(f);
  1981.         }
  1982.  
  1983.         /**
  1984.          * Determine if the object is enabled.
  1985.          *
  1986.          * @return true if object is enabled; otherwise, false
  1987.          */
  1988.         public boolean isEnabled() {
  1989.             return JComponent.this.isEnabled();
  1990.         }
  1991.  
  1992.         /**
  1993.          * Set the enabled state of the object.
  1994.          *
  1995.          * @param b if true, enables this object; otherwise, disables it 
  1996.          */
  1997.         public void setEnabled(boolean b) {
  1998.             boolean old = JComponent.this.isEnabled();
  1999.             JComponent.this.setEnabled(b);
  2000.             if (b != old) {
  2001.                 if (accessibleContext != null) {
  2002.                     if (b) {
  2003.                         accessibleContext.firePropertyChange(
  2004.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2005.                                 null, AccessibleState.ENABLED);
  2006.                     } else {
  2007.                         accessibleContext.firePropertyChange(
  2008.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2009.                                 AccessibleState.ENABLED, null);
  2010.                     }
  2011.                 }
  2012.             }
  2013.         }
  2014.         
  2015.         /**
  2016.          * Determine if the object is visible.  Note: this means that the
  2017.          * object intends to be visible; however, it may not in fact be
  2018.          * showing on the screen because one of the objects that this object
  2019.          * is contained by is not visible.  To determine if an object is
  2020.          * showing on the screen, use isShowing().
  2021.          *
  2022.          * @return true if object is visible; otherwise, false
  2023.          */
  2024.         public boolean isVisible() {
  2025.             return JComponent.this.isVisible();
  2026.         }
  2027.  
  2028.         /**
  2029.          * Set the visible state of the object.
  2030.          *
  2031.          * @param b if true, shows this object; otherwise, hides it 
  2032.          */
  2033.         public void setVisible(boolean b) {
  2034.             boolean old = JComponent.this.isVisible();
  2035.             JComponent.this.setVisible(b);
  2036.             if (b != old) {
  2037.                 if (accessibleContext != null) {
  2038.                     if (b) {
  2039.                         accessibleContext.firePropertyChange(
  2040.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2041.                                 null, AccessibleState.VISIBLE);
  2042.                     } else {
  2043.                         accessibleContext.firePropertyChange(
  2044.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2045.                                 AccessibleState.VISIBLE, null);
  2046.                     }
  2047.                 }
  2048.             }
  2049.         }
  2050.  
  2051.         /**
  2052.          * Determine if the object is showing.  This is determined by checking
  2053.          * the visibility of the object and ancestors of the object.  Note: 
  2054.          * this will return true even if the object is obscured by another 
  2055.          * (for example, it happens to be underneath a menu that was pulled 
  2056.          * down).
  2057.          *
  2058.          * @return true if object is showing; otherwise, false
  2059.          */
  2060.         public boolean isShowing() {
  2061.             return JComponent.this.isShowing();
  2062.         }
  2063.  
  2064.         /** 
  2065.          * Checks whether the specified point is within this object's bounds,
  2066.          * where the point's x and y coordinates are defined to be relative to 
  2067.          * the coordinate system of the object. 
  2068.          *
  2069.          * @param p the Point relative to the coordinate system of the object
  2070.          * @return true if object contains Point; otherwise false
  2071.          */
  2072.         public boolean contains(Point p) {
  2073.             return JComponent.this.contains(p);
  2074.         }
  2075.     
  2076.         /** 
  2077.          * Returns the location of the object on the screen.
  2078.          *
  2079.          * @return location of object on screen -- can be null if this object
  2080.          * is not on the screen
  2081.          */
  2082.         public Point getLocationOnScreen() {
  2083.             if (JComponent.this.isShowing()) {
  2084.                 return JComponent.this.getLocationOnScreen();
  2085.             } else {
  2086.                 return null;
  2087.             }
  2088.         }
  2089.  
  2090.         /** 
  2091.          * Gets the location of the object relative to the parent in the form 
  2092.          * of a point specifying the object's top-left corner in the screen's 
  2093.          * coordinate space.
  2094.          *
  2095.          * @return An instance of Point representing the top-left corner of 
  2096.          * the objects's bounds in the coordinate space of the screen; null if
  2097.          * this object or its parent are not on the screen
  2098.          */
  2099.         public Point getLocation() {
  2100.             return JComponent.this.getLocation();
  2101.         }
  2102.  
  2103.         /** 
  2104.          * Sets the location of the object relative to the parent.
  2105.          */
  2106.         public void setLocation(Point p) {
  2107.             JComponent.this.setLocation(p);
  2108.         }
  2109.  
  2110.         /** 
  2111.          * Gets the bounds of this object in the form of a Rectangle object. 
  2112.          * The bounds specify this object's width, height, and location
  2113.          * relative to its parent. 
  2114.          *
  2115.          * @return A rectangle indicating this component's bounds; null if 
  2116.          * this object is not on the screen.
  2117.          */
  2118.         public Rectangle getBounds() {
  2119.             return JComponent.this.getBounds();
  2120.         }
  2121.  
  2122.         /** 
  2123.          * Sets the bounds of this object in the form of a Rectangle object. 
  2124.          * The bounds specify this object's width, height, and location
  2125.          * relative to its parent.
  2126.          *      
  2127.          * @param A rectangle indicating this component's bounds
  2128.          */
  2129.         public void setBounds(Rectangle r) {
  2130.             JComponent.this.setBounds(r);
  2131.         }
  2132.  
  2133.         /** 
  2134.          * Returns the size of this object in the form of a Dimension object. 
  2135.          * The height field of the Dimension object contains this objects's
  2136.          * height, and the width field of the Dimension object contains this 
  2137.          * object's width. 
  2138.          *
  2139.          * @return A Dimension object that indicates the size of this 
  2140.          *         component; null if this object is not on the screen
  2141.          */
  2142.         public Dimension getSize() {
  2143.             return JComponent.this.getSize();
  2144.         }
  2145.  
  2146.         /** 
  2147.          * Resizes this object so that it has width width and height. 
  2148.          *      
  2149.          * @param d - The dimension specifying the new size of the object. 
  2150.          */
  2151.         public void setSize(Dimension d) {
  2152.             JComponent.this.setSize(d);
  2153.         }
  2154.  
  2155.         /**
  2156.          * Returns the Accessible child, if one exists, contained at the local
  2157.          * coordinate Point.
  2158.          *
  2159.          * @param p The point defining the top-left corner of the Accessible, 
  2160.          * given in the coordinate space of the object's parent. 
  2161.          * @return the Accessible, if it exists, at the specified location; 
  2162.          * else null
  2163.          */
  2164.         public Accessible getAccessibleAt(Point p) {
  2165.         return SwingUtilities.getAccessibleAt(JComponent.this, p);
  2166.         }
  2167.  
  2168.         /**
  2169.          * Returns whether this object can accept focus or not.
  2170.          *
  2171.          * @return true if object can accept focus; otherwise false
  2172.          */
  2173.         public boolean isFocusTraversable() {
  2174.             return JComponent.this.isFocusTraversable();
  2175.         }
  2176.  
  2177.         /**
  2178.          * Requests focus for this object.
  2179.          */
  2180.         public void requestFocus() {
  2181.             JComponent.this.requestFocus();
  2182.         }
  2183.  
  2184.         /**
  2185.          * Adds the specified focus listener to receive focus events from this 
  2186.          * component. 
  2187.          *
  2188.          * @param l the focus listener
  2189.          */
  2190.         public void addFocusListener(FocusListener l) {
  2191.             JComponent.this.addFocusListener(l);
  2192.         }
  2193.  
  2194.         /**
  2195.          * Removes the specified focus listener so it no longer receives focus 
  2196.          * events from this component.
  2197.          *
  2198.          * @param l the focus listener
  2199.          */
  2200.         public void removeFocusListener(FocusListener l) {
  2201.             JComponent.this.removeFocusListener(l);
  2202.         }
  2203.  
  2204.     } // inner class AccessibleJComponent
  2205.  
  2206.  
  2207.     private Dictionary getClientProperties() {
  2208.         if (clientProperties == null) {
  2209.             clientProperties = new Hashtable(2);
  2210.         }
  2211.         return clientProperties;
  2212.     }
  2213.  
  2214.     /**
  2215.      * A convenience method for looking up a property value. It is
  2216.      * equivalent to:
  2217.      * <pre>
  2218.      * getClientProperties().get(key);
  2219.      * </pre>
  2220.      * 
  2221.      * @return the value of this property or null
  2222.      * @see #putClientProperty
  2223.      * @see #getClientProperty
  2224.      */
  2225.     public final Object getClientProperty(Object key) {
  2226.         return getClientProperties().get(key);
  2227.     }
  2228.  
  2229.  
  2230.     /**
  2231.      * A convenience method for storing up a property value. It is
  2232.      * equivalent to:
  2233.      * <pre>
  2234.      * getClientProperties().put(key, value);
  2235.      * </pre>
  2236.      * If value is null this method will remove the property
  2237.      * This method fires PropertyChangeEvents to notify interested
  2238.      * parties of changes to a client property.
  2239.      * 
  2240.      * @see #getClientProperty
  2241.      * @see #getClientProperty
  2242.      */
  2243.     public final void putClientProperty(Object key, Object value) {
  2244.         Object oldValue = getClientProperties().get(key);
  2245.  
  2246.         if (value != null) {
  2247.             getClientProperties().put(key, value);
  2248.         } else {
  2249.             getClientProperties().remove(key);
  2250.         }
  2251.  
  2252.         firePropertyChange(key.toString(), oldValue, value);
  2253.     }
  2254.  
  2255.     
  2256.     /* --- Transitional java.awt.Component Support --- 
  2257.      * 
  2258.      * The methods and fields in this section will migrate to 
  2259.      * java.awt.Component in the next JDK release.
  2260.      *
  2261.      */
  2262.  
  2263.     private PropertyChangeSupport changeSupport;
  2264.  
  2265.  
  2266.     /**
  2267.      * Returns true if this component is a lightweight, i.e. if it doesn't
  2268.      * have a native window system peer.
  2269.      * <p>
  2270.      * This method will migrate to java.awt.Component in the next major JDK release
  2271.      *
  2272.      * @return true if this component is a lightweight
  2273.      */
  2274.     public static boolean isLightweightComponent(Component c) {
  2275.         return c.getPeer() instanceof java.awt.peer.LightweightPeer;
  2276.     }
  2277.  
  2278.  
  2279.     /** 
  2280.      * Moves and resizes this component. 
  2281.      *
  2282.      * @see java.awt.Component#setBounds
  2283.      */
  2284.     public void reshape(int x, int y, int w, int h) {
  2285.         if(isShowing()) {
  2286.             /* If there is an intersection between the new bounds and the old 
  2287.              * one, refresh only the visible rects 
  2288.              */
  2289.             if(!((_bounds.x + _bounds.width <= x) ||
  2290.                  (_bounds.y + _bounds.height <= y) ||
  2291.                  (_bounds.x >= (x + w)) ||
  2292.                  (_bounds.y >= (y + h)))) {
  2293.                 Rectangle[] rev = SwingUtilities.computeDifference(getBounds(),
  2294.                                                                    new Rectangle(x,y,w,h));
  2295.                 int i,c;
  2296.                 Container parent = getParent();
  2297.                 //                System.out.println("*** Start ****");
  2298.                 for(i=0,c=rev.length ; i < c ; i++) {
  2299.                     parent.repaint(rev[i].x,rev[i].y,rev[i].width,rev[i].height);
  2300.                     //                    System.out.println("Repaint " + rev[i]);
  2301.                 }
  2302.             } else {
  2303.                 getParent().repaint(_bounds.x,_bounds.y,_bounds.width,_bounds.height);
  2304.             }
  2305.         }
  2306.         _bounds.setBounds(x, y, w, h);
  2307.         super.reshape(x, y, w, h);
  2308.     }
  2309.  
  2310.     /** 
  2311.      * Moves and resizes this component. 
  2312.      *
  2313.      * @see java.awt.Component#setBounds
  2314.      */
  2315.     public void setBounds(Rectangle r) {
  2316.         _bounds.setBounds(r);
  2317.         super.setBounds(r);
  2318.     }
  2319.  
  2320.  
  2321.     /** 
  2322.      * Store the bounds of this component into "return value" <b>rv</b> and 
  2323.      * return <b>rv</b>.  If rv is null a new Rectangle is allocated.
  2324.      * This version of getBounds() is useful if the caller
  2325.      * wants to avoid allocating a new Rectangle object on the heap.
  2326.      * 
  2327.      * @param rv the return value, modified to the components bounds
  2328.      * @return rv
  2329.      */
  2330.     public Rectangle getBounds(Rectangle rv) {
  2331.     if (rv == null) {
  2332.         return new Rectangle(getX(), getY(), getWidth(), getHeight());
  2333.     }
  2334.     else {
  2335.         rv.setBounds(getX(), getY(), getWidth(), getHeight());
  2336.         return rv;
  2337.     }
  2338.     }
  2339.  
  2340.  
  2341.     /**
  2342.      * Store the width/height of this component into "return value" <b>rv</b> 
  2343.      * and return <b>rv</b>.   If rv is null a new Dimension object is
  2344.      * allocated.  This version of getSize() is useful if the 
  2345.      * caller wants to avoid allocating a new Dimension object on the heap.
  2346.      * 
  2347.      * @param rv the return value, modified to the components size
  2348.      * @return rv
  2349.      */
  2350.     public Dimension getSize(Dimension rv) {
  2351.     if (rv == null) {
  2352.         return new Dimension(getWidth(), getHeight());
  2353.     }
  2354.     else {
  2355.         rv.setSize(getWidth(), getHeight());
  2356.         return rv;
  2357.     }
  2358.     }
  2359.  
  2360.  
  2361.     /**
  2362.      * Store the x,y origin of this component into "return value" <b>rv</b> 
  2363.      * and return <b>rv</b>.   If rv is null a new Point is allocated.
  2364.      * This version of getLocation() is useful if the 
  2365.      * caller wants to avoid allocating a new Point object on the heap.
  2366.      * 
  2367.      * @param rv the return value, modified to the components location
  2368.      * @return rv
  2369.      */
  2370.     public Point getLocation(Point rv) {
  2371.     if (rv == null) {
  2372.         return new Point(getX(), getY());
  2373.     }
  2374.     else {
  2375.         rv.setLocation(getX(), getY());
  2376.         return rv;
  2377.     }
  2378.     }
  2379.  
  2380.  
  2381.     /** 
  2382.      * Return the current x coordinate of the components origin.
  2383.      * This method is preferable to writing component.getBounds().x,
  2384.      * or component.getLocation().x because it doesn't cause any
  2385.      * heap allocations.
  2386.      * <p>
  2387.      * This method will migrate to java.awt.Component in the next major JDK release
  2388.      * 
  2389.      * @return the current x coordinate of the components origin.
  2390.      */
  2391.     public int getX() { return _bounds.x; }
  2392.  
  2393.  
  2394.     /** 
  2395.      * Return the current y coordinate of the components origin.
  2396.      * This method is preferable to writing component.getBounds().y,
  2397.      * or component.getLocation().y because it doesn't cause any
  2398.      * heap allocations.
  2399.      * <p>
  2400.      * This method will migrate to java.awt.Component in the next major JDK release
  2401.      * 
  2402.      * @return the current y coordinate of the components origin.
  2403.      */
  2404.     public int getY() { return _bounds.y; }
  2405.  
  2406.  
  2407.     /** 
  2408.      * Return the current width of this component.
  2409.      * This method is preferable to writing component.getBounds().width,
  2410.      * or component.getSize().width because it doesn't cause any
  2411.      * heap allocations.
  2412.      * <p>
  2413.      * This method will migrate to java.awt.Component in the next major JDK release
  2414.      * 
  2415.      * @return the current width of this component.
  2416.      */
  2417.     public int getWidth() { return _bounds.width; }
  2418.  
  2419.  
  2420.     /** 
  2421.      * Return the current height of this component.
  2422.      * This method is preferable to writing component.getBounds().height,
  2423.      * or component.getSize().height because it doesn't cause any
  2424.      * heap allocations.
  2425.      * <p>
  2426.      * This method will migrate to java.awt.Component in the next major JDK release
  2427.      * 
  2428.      * @return the current height of this component.
  2429.      */
  2430.     public int getHeight() { return _bounds.height; }
  2431.  
  2432.  
  2433.     /**
  2434.      * Returns true if this Component has the keyboard focus.
  2435.      * <p>
  2436.      * This method will migrate to java.awt.Component in the next major JDK release
  2437.      * 
  2438.      * @return true if this Component has the keyboard focus.
  2439.      */
  2440.     public boolean hasFocus() {
  2441.         return getFlag(HAS_FOCUS);
  2442.     }
  2443.  
  2444.  
  2445.     /**
  2446.      * Returns true if this component is completely opaque.
  2447.      * <p>
  2448.      * An opaque component paints every pixel within its
  2449.      * rectangular region. A non-opaque component paints only some of
  2450.      * its pixels, allowing the pixels underneath it to "show through".
  2451.      * A component that does not fully paint its pixels therefore
  2452.      * provides a degree of transparency.
  2453.      * <p>
  2454.      * Subclasses that guarantee to always completely paint their contents should 
  2455.      * override this method and return true. 
  2456.      * <p>
  2457.      * This method will migrate to java.awt.Component in the next major JDK release
  2458.      * 
  2459.      * @return true if this component is completely opaque.
  2460.      * @see #setOpaque
  2461.      */
  2462.     public boolean isOpaque() {
  2463.         return getFlag(IS_OPAQUE);
  2464.     }
  2465.  
  2466.  
  2467.     /**
  2468.      * If true the components background will be filled with the 
  2469.      * background color. Otherwise, the background is transparent,
  2470.      * and whatever is underneath will show through. 
  2471.      * <p>
  2472.      * The default value of this property is false.
  2473.      * <p>
  2474.      * This is a JavaBeans bound property.
  2475.      * 
  2476.      * @see #isOpaque
  2477.      */
  2478.     public void setOpaque(boolean isOpaque) {
  2479.         boolean oldValue = getFlag(IS_OPAQUE);
  2480.         setFlag(IS_OPAQUE, isOpaque);
  2481.         firePropertyChange("opaque", oldValue, isOpaque);
  2482.     }
  2483.  
  2484.  
  2485.     /**
  2486.      * If the specified retangle is completely obscured by any of this
  2487.      * components opaque children then return true.  Only direct children 
  2488.      * are considered, more distant descendants are ignored.  A JComponent 
  2489.      * is opaque if JComponent.isOpaque() returns true, other lightweight 
  2490.      * components are always considered transparent, and heavyweight components 
  2491.      * are always considered opaque.
  2492.      * 
  2493.      * @return true if the specified rectangle is obscured by an opaque child
  2494.      */
  2495.     boolean rectangleIsObscured(int x,int y,int width,int height) 
  2496.     {
  2497.         Component children[] = getComponents();
  2498.  
  2499.  
  2500.         if(children == null) {
  2501.             return false;
  2502.         }
  2503.  
  2504.         for(int i = 0; i < children.length; i++) {
  2505.             Component child = children[i];
  2506.             Rectangle childBounds;
  2507.  
  2508.             if (child instanceof JComponent) {
  2509.                 childBounds = ((JComponent)child)._bounds;
  2510.             } else {
  2511.                 childBounds = child.getBounds();
  2512.             }
  2513.  
  2514.             if (x >= childBounds.x && (x + width) <= (childBounds.x + childBounds.width) &&
  2515.                 y >= childBounds.y && (y + height) <= (childBounds.y + childBounds.height)) {
  2516.  
  2517.                 if(child instanceof JComponent) {
  2518.                     return ((JComponent)child).isOpaque();
  2519.                 } else {
  2520.                     /** Sometimes an heavy weight can have a bound larger than it's peer size
  2521.                      *  so we should always draw under heavy weights
  2522.                      */
  2523.                     return false;
  2524.                 }
  2525.             }
  2526.         }
  2527.         
  2528.         return false;
  2529.     }
  2530.  
  2531.  
  2532.     /**
  2533.      * Returns the Component's "visible rect rectangle" -  the 
  2534.      * intersection of the visible rectangles for this component
  2535.      * and all of its ancestors.  The return value is stored in 
  2536.      * <code>visibleRect</code>
  2537.      * 
  2538.      * @see #getVisibleRect
  2539.      */
  2540.     static final void computeVisibleRect(Component c, Rectangle visibleRect) {
  2541.         Container p = c.getParent();
  2542.         Rectangle bounds = c.getBounds();
  2543.  
  2544.         if (p == null || p instanceof Window || p instanceof Applet) {
  2545.             visibleRect.setBounds(0, 0, bounds.width, bounds.height);
  2546.         } else {
  2547.             computeVisibleRect(p, visibleRect);
  2548.             visibleRect.x -= bounds.x;
  2549.             visibleRect.y -= bounds.y;
  2550.             SwingUtilities.computeIntersection(0,0,bounds.width,bounds.height,visibleRect);
  2551.         }
  2552.     }
  2553.  
  2554.  
  2555.     /**
  2556.      * Returns the Component's "visible rect rectangle" -  the 
  2557.      * intersection of the visible rectangles for this component
  2558.      * and all of its ancestors.  The return value is stored in 
  2559.      * <code>visibleRect</code>
  2560.      * 
  2561.      * @see #getVisibleRect
  2562.      */
  2563.     public void computeVisibleRect(Rectangle visibleRect) {
  2564.         computeVisibleRect(this, visibleRect);
  2565.     }
  2566.  
  2567.  
  2568.     /**
  2569.      * Returns the Component's "visible rectangle" -  the 
  2570.      * intersection of this components visible rectangle:
  2571.      * <pre>
  2572.      * new Rectangle(0, 0, getWidth(), getHeight());
  2573.      * </pre>
  2574.      * and all of its ancestors visible Rectangles.
  2575.      * 
  2576.      * @return the visible rectangle
  2577.      */
  2578.     public Rectangle getVisibleRect() {
  2579.         Rectangle visibleRect = new Rectangle();
  2580.  
  2581.         computeVisibleRect(visibleRect);
  2582.         return visibleRect;
  2583.     }
  2584.  
  2585.  
  2586.     /**
  2587.      * Support for reporting bound property changes.  If oldValue and 
  2588.      * newValue are not equal and the PropertyChangeEvent listener list 
  2589.      * isn't empty, then fire a PropertyChange event to each listener.
  2590.      * This method has an overloaded method for each primitive type.  For
  2591.      * example, here's how to write a bound property set method whose
  2592.      * value is an int:
  2593.      * <pre>
  2594.      * public void setFoo(int newValue) {
  2595.      *     int oldValue = foo;
  2596.      *     foo = newValue;
  2597.      *     firePropertyChange("foo", oldValue, newValue);
  2598.      * }
  2599.      * </pre>
  2600.      * <p>
  2601.      * This method will migrate to java.awt.Component in the next major JDK release
  2602.      * 
  2603.      * @param propertyName  The programmatic name of the property that was changed.
  2604.      * @param oldValue  The old value of the property.
  2605.      * @param newValue  The new value of the property.
  2606.      * @see java.beans.PropertyChangeSupport
  2607.      */
  2608.     protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
  2609.         if (changeSupport != null) {
  2610.             changeSupport.firePropertyChange(propertyName, oldValue, newValue);
  2611.         }
  2612.     }
  2613.  
  2614.     /*
  2615.      * PENDING(hmuller) in JDK1.2 the following firePropertyChange overloads
  2616.      * should additional check for a non-empty listener list with
  2617.      * changeSupport.hasListeners(propertyName) before calling firePropertyChange.
  2618.      */
  2619.  
  2620.     /**
  2621.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2622.      */
  2623.     public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {
  2624.         if ((changeSupport != null) && (oldValue != newValue)) {
  2625.             changeSupport.firePropertyChange(propertyName, new Byte(oldValue), new Byte(newValue));
  2626.         }
  2627.     }
  2628.  
  2629.     /**
  2630.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2631.      */
  2632.      public void firePropertyChange(String propertyName, char oldValue, char newValue) {
  2633.          if ((changeSupport != null) && (oldValue != newValue)) {
  2634.              changeSupport.firePropertyChange(propertyName, new Character(oldValue), new Character(newValue));
  2635.          }
  2636.     }
  2637.  
  2638.     /**
  2639.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2640.      */
  2641.     public void firePropertyChange(String propertyName, short oldValue, short newValue) {
  2642.         if ((changeSupport != null) && (oldValue != newValue)) {
  2643.             changeSupport.firePropertyChange(propertyName, new Short(oldValue), new Short(newValue));
  2644.         }
  2645.     }
  2646.  
  2647.     /**
  2648.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2649.      */
  2650.     public void firePropertyChange(String propertyName, int oldValue, int newValue) {
  2651.         if ((changeSupport != null) && (oldValue != newValue)) {
  2652.             changeSupport.firePropertyChange(propertyName, new Integer(oldValue), new Integer(newValue));
  2653.         }
  2654.     }
  2655.  
  2656.     /**
  2657.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2658.      */
  2659.     public void firePropertyChange(String propertyName, long oldValue, long newValue) {
  2660.         if ((changeSupport != null) && (oldValue != newValue)) {
  2661.             changeSupport.firePropertyChange(propertyName, new Long(oldValue), new Long(newValue));
  2662.         }
  2663.     }
  2664.  
  2665.     /**
  2666.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2667.      */
  2668.     public void firePropertyChange(String propertyName, float oldValue, float newValue) {
  2669.         if ((changeSupport != null) && (oldValue != newValue)) {
  2670.             changeSupport.firePropertyChange(propertyName, new Float(oldValue), new Float(newValue));
  2671.         }
  2672.     }
  2673.  
  2674.     /**
  2675.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2676.      */
  2677.     public void firePropertyChange(String propertyName, double oldValue, double newValue) {
  2678.         if ((changeSupport != null) && (oldValue != newValue)) {
  2679.             changeSupport.firePropertyChange(propertyName, new Double(oldValue), new Double(newValue));
  2680.         }
  2681.     }
  2682.  
  2683.     /**
  2684.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2685.      */
  2686.     public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
  2687.         if ((changeSupport != null) && (oldValue != newValue)) {
  2688.             changeSupport.firePropertyChange(propertyName, new Boolean(oldValue), new Boolean(newValue));
  2689.         }
  2690.     }
  2691.  
  2692.  
  2693.     /**
  2694.      * Add a PropertyChangeListener to the listener list.
  2695.      * The listener is registered for all properties.
  2696.      * <p>
  2697.      * A PropertyChangeEvent will get fired in response to setting
  2698.      * a bound property, e.g. setFont, setBackground, or setForeground.
  2699.      * Note that if the current component is inheriting its foreground, 
  2700.      * background, or font from its container, then no event will be 
  2701.      * fired in response to a change in the inherited property.
  2702.      * <p>
  2703.      * This method will migrate to java.awt.Component in the next major JDK release
  2704.      *
  2705.      * @param listener  The PropertyChangeListener to be added
  2706.      */
  2707.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
  2708.         if (changeSupport == null) {
  2709.             changeSupport = new java.beans.PropertyChangeSupport(this);
  2710.         }
  2711.         changeSupport.addPropertyChangeListener(listener);
  2712.     }
  2713.  
  2714.  
  2715.     /**
  2716.      * Remove a PropertyChangeListener from the listener list.
  2717.      * This removes a PropertyChangeListener that was registered
  2718.      * for all properties.
  2719.      * <p>
  2720.      * This method will migrate to java.awt.Component in the next major JDK release
  2721.      *
  2722.      * @param listener  The PropertyChangeListener to be removed
  2723.      */
  2724.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
  2725.         if (changeSupport != null) {
  2726.             changeSupport.removePropertyChangeListener(listener);
  2727.         }
  2728.     }
  2729.  
  2730.  
  2731.     /**
  2732.      * Support for reporting constrained property changes.  This method can be called
  2733.      * when a constrained property has changed and it will send the appropriate
  2734.      * PropertyChangeEvent to any registered VetoableChangeListeners.
  2735.      * <p>
  2736.      * This method will migrate to java.awt.Component in the next major JDK release
  2737.      *
  2738.      * @exception PropertyVetoException when the attempt to set the property is vetoed
  2739.      *            by the receiver.
  2740.      */
  2741.     protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue) 
  2742.         throws java.beans.PropertyVetoException
  2743.     {
  2744.         if (vetoableChangeSupport == null) {
  2745.             return;
  2746.         }
  2747.         vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
  2748.     }
  2749.  
  2750.  
  2751.     /**
  2752.      * Add a VetoableChangeListener to the listener list.
  2753.      * The listener is registered for all properties.
  2754.      * <p>
  2755.      * This method will migrate to java.awt.Component in the next major JDK release
  2756.      * 
  2757.      * @param listener  The VetoableChangeListener to be added
  2758.      */
  2759.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener) {
  2760.         if (vetoableChangeSupport == null) {
  2761.             vetoableChangeSupport = new java.beans.VetoableChangeSupport(this);
  2762.         }
  2763.         vetoableChangeSupport.addVetoableChangeListener(listener);
  2764.     }
  2765.  
  2766.  
  2767.     /**
  2768.      * Remove a VetoableChangeListener from the listener list.
  2769.      * This removes a VetoableChangeListener that was registered
  2770.      * for all properties.
  2771.      * <p>
  2772.      * This method will migrate to java.awt.Component in the next major JDK release
  2773.      *
  2774.      * @param listener  The VetoableChangeListener to be removed
  2775.      */
  2776.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener) {
  2777.         if (vetoableChangeSupport == null) {
  2778.             return;
  2779.         }
  2780.         vetoableChangeSupport.removeVetoableChangeListener(listener);
  2781.     }
  2782.  
  2783.  
  2784.     /**
  2785.      * Returns the top-level ancestor of this component (either the
  2786.      * containing Window or Applet), or null if this component has not 
  2787.      * been added to any container.
  2788.      * 
  2789.      * @return the top-level Container which this component is in.
  2790.      */
  2791.     public Container getTopLevelAncestor() {
  2792.         for(Container p = this; p != null; p = p.getParent()) {
  2793.             if(p instanceof Window || p instanceof Applet) {
  2794.                 return p;
  2795.             }
  2796.         }
  2797.         return null;
  2798.     }
  2799.  
  2800.  
  2801.     /**
  2802.      * Registers <i>listener</i> so that it will receive AncestorEvents
  2803.      * when it or any of its ancestors move or are made visible / invisible.
  2804.      * Events are also sent when the component or its ancestors are added
  2805.      * or removed from the Component hierarchy
  2806.      * <p>
  2807.      * This method will migrate to java.awt.Component in the next major JDK release
  2808.      *
  2809.      * @see AncestorEvent
  2810.      */
  2811.     public void addAncestorListener(AncestorListener listener) {
  2812.         if (ancestorNotifier == null) {
  2813.             ancestorNotifier = new AncestorNotifier(this);
  2814.         }
  2815.         ancestorNotifier.addAncestorListener(listener);
  2816.     }
  2817.  
  2818.     /**
  2819.      * Unregisters <i>listener</i> so that it will no longer receive
  2820.      * AncestorEvents
  2821.      * <p>
  2822.      * This method will migrate to java.awt.Component in the next major JDK release
  2823.      *
  2824.      * @see #addAncestorListener
  2825.      */
  2826.     public void removeAncestorListener(AncestorListener listener) {
  2827.         if (ancestorNotifier == null) {
  2828.             return;
  2829.         }
  2830.         ancestorNotifier.removeAncestorListener(listener);
  2831.         if (ancestorNotifier.listenerList.getListenerList().length == 0) {
  2832.             ancestorNotifier.removeAllListeners();
  2833.             ancestorNotifier = null;
  2834.         }
  2835.     }
  2836.  
  2837.  
  2838.     /**
  2839.      * Notification to this component that it now has a parent component.
  2840.      * When this method is invoked, the chain of parent components is
  2841.      * set up with KeyboardAction event listeners.
  2842.      *
  2843.      * @see #registerKeyboardAction
  2844.      */
  2845.     public void addNotify() {
  2846.         super.addNotify();
  2847.         firePropertyChange("ancestor", null, getParent());
  2848.     }
  2849.  
  2850.  
  2851.     /**
  2852.      * Notification to this component that it no longer has a parent component.
  2853.      * When this method is invoked, any KeyboardActions set up in the
  2854.      * the chain of parent components are removed.
  2855.      *
  2856.      * @see #registerKeyboardAction
  2857.      */
  2858.     public void removeNotify() {
  2859.         super.removeNotify();
  2860.         // This isn't strictly correct.  The event shouldn't be
  2861.         // fired until *after* the parent is set to null.  But
  2862.         // we only get notified before that happens
  2863.         firePropertyChange("ancestor", getParent(), null);
  2864.     }
  2865.  
  2866.  
  2867.     /**
  2868.      * Adds the specified region to the dirty region list if the component
  2869.      * is showing.  The component will be repainted after all of the 
  2870.      * currently pending events have been dispatched.
  2871.      * 
  2872.      * @see java.awt.Component#isShowing
  2873.      * @see RepaintManager#addDirtyRegion
  2874.      */
  2875.     public void repaint(long tm, int x, int y, int width, int height) {
  2876.         RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
  2877.     }
  2878.  
  2879.  
  2880.     /**
  2881.      * Adds the specified region to the dirty region list if the component
  2882.      * is showing.  The component will be repainted after all of the 
  2883.      * currently pending events have been dispatched.
  2884.      * 
  2885.      * @see java.awt.Component#isShowing
  2886.      * @see RepaintManager#addDirtyRegion
  2887.      */
  2888.     public void repaint(Rectangle r) {
  2889.         repaint(0,r.x,r.y,r.width,r.height);
  2890.     }
  2891.  
  2892.  
  2893.     /**
  2894.      * Support for deferred automatic layout.
  2895.      * <p>
  2896.      * Calls invalidate() and then adds this components validateRoot
  2897.      * to a list of components that need to be validated.  Validation 
  2898.      * will occur after all currently pending events have been dispatched.  
  2899.      * By default only JScrollPane.isValidateRoot() returns true.  In other
  2900.      * words after this method is called,  the first JScrollPane that 
  2901.      * contains this component (if any) will be validated.
  2902.      * 
  2903.      * @see java.awt.Component#invalidate
  2904.      * @see java.awt.Container#validate
  2905.      * @see #isValidateRoot
  2906.      * @see RepaintManager#addInvalidComponent
  2907.      */
  2908.     public void revalidate() {
  2909.         if (SwingUtilities.isEventDispatchThread()) {
  2910.             invalidate();
  2911.             RepaintManager.currentManager(this).addInvalidComponent(this);
  2912.         }
  2913.         else {
  2914.             Runnable callRevalidate = new Runnable() {
  2915.                 public void run() {
  2916.                     revalidate();
  2917.                 }
  2918.             };
  2919.             SwingUtilities.invokeLater(callRevalidate);
  2920.         }
  2921.     }
  2922.  
  2923.  
  2924.     /** 
  2925.      * If this method returns true, revalidate() calls by descendants of 
  2926.      * this component will cause the entire tree beginning with this root
  2927.      * to be validated.  Returns false by default.  JScrollPane overrides
  2928.      * this method and returns true.
  2929.      * 
  2930.      * @return false
  2931.      * @see #revalidate
  2932.      * @see java.awt.Component#invalidate
  2933.      * @see java.awt.Container#validate
  2934.      */
  2935.     public boolean isValidateRoot() {
  2936.         return false;
  2937.     }
  2938.  
  2939.  
  2940.     /**
  2941.      * Returns true if this component tiles its children, i.e. if
  2942.      * it can guarantee that the children will not overlap.  The 
  2943.      * repainting system is substantially more efficient in this
  2944.      * common case.  JComponent subclasses that can't make this 
  2945.      * guarantee, e.g. JLayeredPane, should override this method
  2946.      * to return false.
  2947.      * 
  2948.      * @return true if this components children don't overlap
  2949.      */
  2950.     public boolean isOptimizedDrawingEnabled() {
  2951.         return true;
  2952.     }
  2953.  
  2954.  
  2955.     /** 
  2956.      * Paint the specified region in this component and all of its 
  2957.      * descendants that overlap the region, immediately.
  2958.      * <p>
  2959.      * It's rarely neccessary to call this method.  In most cases it's
  2960.      * more efficient to call repaint which defers the actual painting
  2961.      * and can collapse redundant requests into a single paint call.
  2962.      * This method is useful if one needs to update the display while
  2963.      * the current event is being dispatched.
  2964.      *
  2965.      * @see #repaint
  2966.      */
  2967.     public void paintImmediately(int x,int y,int w, int h) {
  2968.         Component c = this;
  2969.         Component parent;
  2970.         Rectangle bounds;
  2971.  
  2972.         if(!isShowing()) {
  2973.             return;
  2974.         }
  2975.         while(!((JComponent)c).isOpaque()) {
  2976.             parent = c.getParent();
  2977.             if(parent != null) {
  2978.                 if(c instanceof JComponent) {
  2979.                     bounds = ((JComponent)c)._bounds;
  2980.                 } else {
  2981.                     bounds = c.getBounds();
  2982.                 }
  2983.                 x += bounds.x;
  2984.                 y += bounds.y;
  2985.                 c = parent;
  2986.             } else {
  2987.                 break;
  2988.             }
  2989.  
  2990.             if(!(c instanceof JComponent)) {
  2991.                 break;
  2992.             }
  2993.         }
  2994.         if(c instanceof JComponent) {
  2995.             ((JComponent)c)._paintImmediately(x,y,w,h);
  2996.         } else {
  2997.             c.repaint(x,y,w,h);
  2998.         }
  2999.     }
  3000.  
  3001.     /** 
  3002.      * Paint the specified region now.
  3003.      * <p>
  3004.      * This method will migrate to java.awt.Component in the next major JDK release
  3005.      */
  3006.     public void paintImmediately(Rectangle r) {
  3007.         paintImmediately(r.x,r.y,r.width,r.height);
  3008.     }
  3009.  
  3010.  
  3011.     void _paintImmediately(int x, int y, int w, int h) {
  3012.         Graphics g;
  3013.         Container c;
  3014.         Rectangle clip = new Rectangle(x,y,w,h);
  3015.         Rectangle b;
  3016.         if(tmpRect == null) {
  3017.             tmpRect = new Rectangle();
  3018.         }
  3019.         tmpRect.x=tmpRect.y=0;
  3020.         int offsetX=0,offsetY=0;
  3021.         int bufferOffsetX=0,bufferOffsetY=0;
  3022.         boolean hasBuffer = false;
  3023.         JComponent bufferedComponent = null;
  3024.         JComponent paintingComponent = this;
  3025.         RepaintManager repaintManager = RepaintManager.currentManager(this);
  3026.  
  3027.         for (c = this; 
  3028.              c != null && !(c instanceof Window) && !(c instanceof Applet); 
  3029.              c = c.getParent()) {
  3030.              if ((c instanceof JComponent) && !(((JComponent)c).isOptimizedDrawingEnabled())) {
  3031.                 paintingComponent = (JComponent)c;
  3032.                 offsetX = offsetY = 0;
  3033.                 hasBuffer = false; /** Get rid of any buffer since we draw from here and
  3034.                                     *  we might draw something larger 
  3035.                                     */
  3036.             } 
  3037.  
  3038.             if(repaintManager.isDoubleBufferingEnabled() && 
  3039.                (c instanceof JComponent) && ((JComponent)c).isDoubleBuffered()) {
  3040.                 hasBuffer = true;
  3041.                 bufferedComponent = (JComponent)c;
  3042.                 bufferOffsetX = offsetX;
  3043.                 bufferOffsetY = offsetY;
  3044.             }
  3045.             if(c instanceof JComponent) {
  3046.                 b = ((JComponent)c)._bounds;
  3047.             } else {
  3048.                 b = c.getBounds();
  3049.             }
  3050.             tmpRect.width = b.width;
  3051.             tmpRect.height = b.height;
  3052.             SwingUtilities.computeIntersection(tmpRect.x,tmpRect.y,tmpRect.width,tmpRect.height,clip);
  3053.             clip.x += b.x;
  3054.             clip.y += b.y;
  3055.             offsetX += b.x;
  3056.             offsetY += b.y;
  3057.         }
  3058.  
  3059.         if(c == null || c.getPeer() == null) {
  3060.             return;
  3061.         }
  3062.  
  3063.         clip.x -= offsetX;
  3064.         clip.y -= offsetY;
  3065.  
  3066.         try {
  3067.             g = SwingGraphics.createSwingGraphics(paintingComponent.getGraphics());
  3068.         } catch(NullPointerException e) {
  3069.             g = null;
  3070.             e.printStackTrace();
  3071.         }
  3072.         
  3073.         if(g == null) {
  3074.             System.err.println("In paintImmediately null graphics");
  3075.             return;
  3076.         }
  3077.  
  3078.         if(hasBuffer) {
  3079.             Image offscreen = repaintManager.getOffscreenBuffer(bufferedComponent,clip.width,clip.height);
  3080.             paintWithBuffer(paintingComponent,g,clip,offscreen);
  3081.             g.dispose();
  3082.         } else {
  3083.             g.setClip(clip.x,clip.y,clip.width,clip.height);
  3084.             try {
  3085.                 paintingComponent.paint(g);
  3086.             } finally {
  3087.                 g.dispose();
  3088.             }
  3089.         }
  3090.     }
  3091.     
  3092.     private void paintWithBuffer(JComponent paintingComponent,Graphics g,Rectangle clip,Image offscreen) {
  3093.         Graphics og = SwingGraphics.createSwingGraphics(offscreen.getGraphics());
  3094.         int bw = offscreen.getWidth(null);
  3095.         int bh = offscreen.getHeight(null);
  3096.         int x,y,maxx,maxy;
  3097.  
  3098.         if(bw > clip.width) {
  3099.             bw = clip.width;
  3100.         }
  3101.         if(bh > clip.height) {
  3102.             bh = clip.height;
  3103.         }
  3104.         
  3105.         try {
  3106.             paintingComponent.setFlag(ANCESTOR_USING_BUFFER,true);
  3107.             paintingComponent.setFlag(IS_PAINTING_TILE,true);
  3108.             for(x = clip.x, maxx = clip.x+clip.width;
  3109.                 x < maxx ;  x += bw ) {
  3110.                 for(y=clip.y, maxy = clip.y + clip.height;
  3111.                     y < maxy ; y += bh) {
  3112.                     if((y+bh) >= maxy && (x+bw) >= maxx) {
  3113.                         paintingComponent.setFlag(IS_PAINTING_TILE,false);
  3114.                     }
  3115.                     og.translate(-x,-y);
  3116.                     og.setClip(x,y,bw,bh); 
  3117.                     paintingComponent.paint(og);
  3118.                     g.setClip(x,y,bw,bh);
  3119.                     g.drawImage(offscreen,x,y,paintingComponent);
  3120.                     og.translate(x,y);
  3121.                 }
  3122.             }
  3123.         } finally {
  3124.             paintingComponent.setFlag(ANCESTOR_USING_BUFFER,false);
  3125.             paintingComponent.setFlag(IS_PAINTING_TILE,false);
  3126.             og.dispose();
  3127.         }
  3128.     }
  3129.  
  3130.  
  3131.     private void setFlag(int aFlag, boolean aValue) {
  3132.         if(aValue) {
  3133.             flags |= (1 << aFlag);
  3134.         } else {
  3135.             flags &= ~(1 << aFlag);
  3136.         }
  3137.     }
  3138.  
  3139.     private boolean getFlag(int aFlag) {
  3140.         int mask = (1 << aFlag);
  3141.         return ((flags & mask) == mask);
  3142.     }
  3143.  
  3144.  
  3145.     /** Buffering **/
  3146.  
  3147.     /** Set whether the receiving component should use a buffer to paint.
  3148.      *  If set to true, all the drawing from this component will be done
  3149.      *  in an offscreen painting buffer. The offscreen painting buffer will
  3150.      *  the be copied onto the screen.
  3151.      *  Swing's painting system always use a maximum of one double buffer.
  3152.      *  If a Component is buffered and one of its ancestor is also buffered,
  3153.      *  the ancestor buffer will be used.
  3154.      */
  3155.     public void setDoubleBuffered(boolean aFlag) {
  3156.         setFlag(IS_DOUBLE_BUFFERED,aFlag);
  3157.     }
  3158.  
  3159.     /** Return whether the receiving component should use a buffer to paint. **/
  3160.     public boolean isDoubleBuffered() {
  3161.         return getFlag(IS_DOUBLE_BUFFERED);
  3162.     }
  3163.  
  3164.     /**
  3165.      * Return the receiving component root pane 
  3166.      */
  3167.     public JRootPane getRootPane() {
  3168.         return SwingUtilities.getRootPane(this);
  3169.     }
  3170.  
  3171.  
  3172.     /** Serialization **/
  3173.  
  3174.     /*
  3175.     private void writeObject(ObjectOutputStream s) throws IOException {
  3176.         s.defaultWriteObject();
  3177.     }
  3178.  
  3179.  
  3180.     private void readObject(ObjectInputStream s) 
  3181.         throws IOException, ClassNotFoundException 
  3182.     {
  3183.         s.defaultReadObject();
  3184.         updateUI();
  3185.     }
  3186.     */
  3187. }
  3188.