home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / JComponent.java < prev    next >
Text File  |  1998-02-26  |  110KB  |  3,185 lines

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