home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / VCafe / Source.bin / ButtonBase.java < prev    next >
Encoding:
Java Source  |  1998-09-14  |  49.6 KB  |  1,615 lines

  1. package symantec.itools.awt;
  2.  
  3. import java.awt.*;
  4. import java.applet.*;
  5. import java.awt.event.KeyEvent;
  6. import java.awt.event.FocusEvent;
  7. import java.awt.event.MouseEvent;
  8. import java.awt.event.ActionEvent;
  9. import java.awt.event.ActionListener;
  10. import java.net.URL;
  11. import java.beans.PropertyVetoException;
  12. import java.beans.PropertyChangeListener;
  13. import java.beans.VetoableChangeListener;
  14. import java.beans.PropertyChangeEvent;
  15. import java.lang.IllegalArgumentException;
  16. import symantec.itools.awt.util.ColorUtils;
  17. import symantec.itools.util.Timer;
  18. import symantec.itools.util.GeneralUtils;
  19. import java.util.ResourceBundle;
  20.  
  21. //    05/30/97    LAB    Updated to support Java 1.1
  22. //    06/24/97    LAB    Made the button behave like a button. i.e. When you press the
  23. //                    button, then move off of it, it responds.  This also affects the
  24. //                    notification process.
  25. //                    Fixed problem which required setNotifyDelay() to be
  26. //                    called before setNotifyWhilePressed().
  27. //    06/26/97    LAB    Changed the way the button is drawn.  Now it uses an offscreen
  28. //                    Image as its drawing buffer via updateButtonImage().  Added
  29. //                    capabilities to allow the button to have a user definable color,
  30. //                    and the highlights are derived from that.  Also added a user
  31. //                    definable border color.
  32. //    06/27/97    LAB    Added UseOffset property to allow the button to draw differently
  33. //                    if the user wants objects in the button (like a direction arrow, or
  34. //                    image) to be offset vertically and horizontally by the bevel height
  35. //                    when the button is drawn is its down state.  Changed the default bevel
  36. //                    height to 2 pixels.
  37. //    07/09/97    LAB    Added LinkURL property and supporting properties/methods/members
  38. //                    to allow buttons to have a URL associated with them by defualt.
  39. //                    Added ShowURLStatus property to allow control over the status
  40. //                    messaging for the linkURL.  Condensed all of the java.awt.whatever
  41. //                    imports to java.awt.* for readability. Added minimumSize() and
  42. //                    preferedSize() methods. Updated the enable() and disable() methods
  43. //                    to the new setEnabled() method.
  44. //    07/13/97    RKM    Fixed misspelling of prefered
  45. //    07/19/97    LAB    Added deprecated preferedSize and minimumSize to call the non-deprecated versions.
  46. //  07/23/97    CAR marked fields transient as needed, inner classes implement java.io.Serializable
  47. //    08/05/97    LAB    Added a call to clipRect in the updateButtonImage method to clip subsequent
  48. //                    drawings to the internal button area (sans border and bevel).
  49. //    08/06/97    LAB    Added buttonImageGraphics as a protected data member for use in child
  50. //                    classes overridden updateButtonImage calls.  This allows the cliping
  51. //                    that is done in the ButtonBase to propagate correctly.
  52. //                    Removed all traces of infoTips.
  53. //  08/23/97    CAR button can now be tabbed to and from
  54. //                  when button has focus on Windows a broken line outline will indicate focus
  55. //  08/25/97    CAR when property showFocus is set to true a broken line outline will indicate focus
  56. //                  on Windows showFocus defaults to true, on all other platforms it defaults to false
  57. //  08/28/97    CAR when showFocus is true and button has focus and not on the Macintosh platform, pressing
  58. //                  the space bar will press the button
  59. //  09/01/97    CAR setAppletContext now also called from addNotify in addition to being called from
  60. //                  validate (validate not called when applet loaded in IE)
  61. //    09/11/97    LAB    Moved code to display URL Link outside check to see if button is pressed
  62. //                    (Addresses Mac Bug #7606).
  63. //    10/05/97    LAB    Changed names of strings in PropertyChangeEvent handling to follow Bean Spec
  64. //                    naming conventions.  Added mechanism for internally constrained properties
  65. //                    to be validated after the component is added to the form to avoid code-gen
  66. //                    order specific dependencies.
  67. //    10/06/97    LAB    Chnaged addNotify to call it's super after listeners are hooked up so
  68. //                    verifyContstrainedPropertyValues will be called after the listeners
  69. //                    are hooked up.  Added simulateClick method.  Changed setBevelHeight
  70. //                    to set the temp value to the current value when changing the current
  71. //                    value.  Changed getBevelHeight to return the temp value if the
  72. //                    component is not added. This fixes a problem at design time where the
  73. //                    component would revert to it's default state after a back run.
  74.  
  75. /**
  76.  * An abstract class used to implement special Symantec buttons.
  77.  * It supports 3-D beveled borders, and the posting of continuous
  78.  * notification events while the button is pressed.
  79.  * <p>
  80.  * @version 1.1, June 26, 1997
  81.  * @author Symantec
  82.  */
  83. public abstract class ButtonBase extends Canvas
  84. {
  85.     /**
  86.      * Constructs a default ButtonBase. The defaults are no notifyWhilePressed,
  87.      * no offset, and a bevel height of 2.
  88.      */
  89.     protected ButtonBase()
  90.     {
  91.         pressed                = false;
  92.         released            = true;
  93.         notifyWhilePressed    = false;
  94.         running                = false;
  95.         notified            = false;
  96.         useOffset            = false;
  97.         showURLStatus        = true;
  98.         isAdded                = false;
  99.         notifyTimer            = null;
  100.         notifyDelay            = 1000;
  101.         bevel                = 2;
  102.         pressedAdjustment    = 0;
  103.         tempBevelHeight        = bevel;
  104.  
  105.         try
  106.         {
  107.             setBorderColor(Color.black);
  108.             setButtonColor(Color.lightGray);
  109.         }
  110.         catch (PropertyVetoException exc) {}
  111.  
  112.         if(symantec.itools.lang.OS.isWindows())
  113.         {
  114.             try {
  115.                 setShowFocus(true);
  116.             } catch (PropertyVetoException e) { }
  117.         }
  118.     }
  119.  
  120.     /**
  121.      * Sets the "height" (cross-section) of a beveled edge, in pixels.
  122.      * @param height the size of the bevel in pixels
  123.      * @exception PropertyVetoException
  124.      * if the specified property value is unacceptable
  125.      * @see #getBevelHeight
  126.      */
  127.     public void setBevelHeight(int height) throws PropertyVetoException
  128.     {
  129.         if(isAdded)
  130.         {
  131.             if(bevel != height)
  132.             {
  133.                 Integer oldValue = new Integer(bevel);
  134.                 Integer newValue = new Integer(height);
  135.  
  136.                 vetos.fireVetoableChange("bevelHeight", oldValue, newValue);
  137.  
  138.                 bevel = height;
  139.                 tempBevelHeight = height;
  140.  
  141.                 repaint();
  142.  
  143.                 changes.firePropertyChange("bevelHeight", oldValue, newValue);
  144.             }
  145.         }
  146.         //We store the value until we are added then set the value to avoid code-gen order dependencies.
  147.         else
  148.         {
  149.             tempBevelHeight = height;
  150.         }
  151.     }
  152.  
  153.     /**
  154.      * Returns the current "height" (cross-section) of a beveled edge, in pixels.
  155.      * @return the current bevel height in pixels.
  156.      * @see #setBevelHeight
  157.      */
  158.     public int getBevelHeight()
  159.     {
  160.         return isAdded ? bevel : tempBevelHeight;
  161.     }
  162.  
  163.     /**
  164.      * Sets whether the button will continually post notify events while pressed.
  165.      * @param flag true to post notify events; false to not post events
  166.      * @exception PropertyVetoException
  167.      * if the specified property value is unacceptable
  168.      * @see #isNotifyWhilePressed
  169.      * @see #setNotifyDelay
  170.      * @see #getNotifyDelay
  171.      */
  172.     public void setNotifyWhilePressed(boolean flag) throws PropertyVetoException
  173.     {
  174.         if(notifyWhilePressed != flag)
  175.         {
  176.             Boolean oldValue = new Boolean(notifyWhilePressed);
  177.             Boolean newValue = new Boolean(flag);
  178.  
  179.             vetos.fireVetoableChange("notifyWhilePressed", oldValue, newValue);
  180.  
  181.             notifyWhilePressed = flag;
  182.  
  183.             if (notifyWhilePressed)
  184.             {
  185.                 notifyTimer = new Timer(notifyDelay, true);
  186.                 notifyTimer.addActionListener(action);
  187.             }
  188.             else if (notifyTimer != null)
  189.             {
  190.                 notifyTimer = null;
  191.             }
  192.  
  193.             changes.firePropertyChange("notifyWhilePressed", oldValue, newValue);
  194.         }
  195.     }
  196.  
  197.     /**
  198.      * Gets whether the button will continuously post events while pressed.
  199.      * @return true if it will continuously post events while pressed, false
  200.      * otherwise
  201.      * @see #setNotifyWhilePressed
  202.      * @see #setNotifyDelay
  203.      * @see #getNotifyDelay
  204.      */
  205.     public boolean isNotifyWhilePressed()
  206.     {
  207.         return notifyWhilePressed;
  208.     }
  209.  
  210.     /**
  211.      * @deprecated
  212.      * @see #isNotifyWhilePressed
  213.      */
  214.     public boolean getNotifyWhilePressed()
  215.     {
  216.         return isNotifyWhilePressed();
  217.     }
  218.  
  219.     /**
  220.      * Sets the notification event delay in milliseconds.
  221.      * @param delay the delay between notification events in milliseconds
  222.      * @exception PropertyVetoException
  223.      * if the specified property value is unacceptable
  224.      * @see #setNotifyWhilePressed
  225.      * @see #getNotifyDelay
  226.      */
  227.     public void setNotifyDelay(int delay) throws PropertyVetoException
  228.     {
  229.         if(notifyDelay != delay)
  230.         {
  231.             Integer oldValue = new Integer(notifyDelay);
  232.             Integer newValue = new Integer(delay);
  233.  
  234.             vetos.fireVetoableChange("notifyDelay", oldValue, newValue);
  235.             notifyDelay = delay;
  236.             if(notifyTimer != null)
  237.                 notifyTimer.setDelay(notifyDelay);
  238.             changes.firePropertyChange("notifyDelay", oldValue, newValue);
  239.         }
  240.     }
  241.  
  242.     /**
  243.      * Returns the current delay in milliseconds between notification events.
  244.      * @see #setNotifyWhilePressed
  245.      * @see #setNotifyDelay
  246.      */
  247.     public int getNotifyDelay()
  248.     {
  249.         return notifyDelay;
  250.     }
  251.  
  252.     /**
  253.      * Sets whether objects in the button will be offset down and to the right
  254.      * bevel height amount or not.
  255.      * This also impacts the way the button is drawn when it is pressed.
  256.      * @param flag true to have objects use the offset; false to have objects not move.
  257.      * @exception PropertyVetoException
  258.      * if the specified property value is unacceptable
  259.      * @see #isUseOffset
  260.      * @see #setBevelHeight
  261.      * @see #getBevelHeight
  262.      */
  263.     public void setUseOffset(boolean flag) throws PropertyVetoException
  264.     {
  265.         if(useOffset != flag)
  266.         {
  267.             Boolean oldValue = new Boolean(useOffset);
  268.             Boolean newValue = new Boolean(flag);
  269.             vetos.fireVetoableChange("useOffset", oldValue, newValue);
  270.  
  271.             useOffset = flag;
  272.             repaint();
  273.  
  274.             changes.firePropertyChange("useOffset", oldValue, newValue);
  275.         }
  276.     }
  277.  
  278.     /**
  279.      * Returns whether this button will be shown as having the focus when the mouse enters.
  280.      * @see #setShowFocus
  281.      */
  282.     public boolean isUseOffset()
  283.     {
  284.         return useOffset;
  285.     }
  286.  
  287.     /**
  288.      * Sets whether this button will be shown as having the focus when the mouse enters.
  289.      * @param flag true to show focus at mouse enter; false to not show at mouse enter
  290.      * @exception PropertyVetoException
  291.      * if the specified property value is unacceptable
  292.      * @see #isShowFocus
  293.      */
  294.     public void setShowFocus(boolean flag) throws PropertyVetoException
  295.     {
  296.         if(showFocus != flag)
  297.         {
  298.             Boolean oldValue = new Boolean(showFocus);
  299.             Boolean newValue = new Boolean(flag);
  300.             vetos.fireVetoableChange("showFocus", oldValue, newValue);
  301.  
  302.             showFocus = flag;
  303.  
  304.             changes.firePropertyChange("showFocus", oldValue, newValue);
  305.         }
  306.     }
  307.  
  308.     /**
  309.      * Returns whether this button will be shown as having the focus when the mouse enters.
  310.      * @see #setShowFocus
  311.      */
  312.     public boolean isShowFocus()
  313.     {
  314.         return showFocus;
  315.     }
  316.  
  317.     /**
  318.      * @deprecated
  319.      * @see #isShowFocus
  320.      */
  321.     public boolean getShowFocus()
  322.     {
  323.         return isShowFocus();
  324.     }
  325.  
  326.     /**
  327.      * Sets whether the linkURL will be displayed in the status area when the mouse
  328.      * is over the button.
  329.      * This flag also controls erasing of the status area after the URL has been displayed.
  330.      * @param flag true if the linkURL will be displayed in the status area when the mouse
  331.      * is over the button; false if not.
  332.      * @exception PropertyVetoException
  333.      * if the specified property value is unacceptable
  334.      * @see #isShowURLStatus
  335.      */
  336.     public void setShowURLStatus(boolean flag) throws PropertyVetoException
  337.     {
  338.         if(showURLStatus != flag)
  339.         {
  340.             Boolean oldValue = new Boolean(showURLStatus);
  341.             Boolean newValue = new Boolean(flag);
  342.             vetos.fireVetoableChange("showURLStatus", oldValue, newValue);
  343.  
  344.             showURLStatus = flag;
  345.  
  346.             changes.firePropertyChange("showURLStatus", oldValue, newValue);
  347.         }
  348.     }
  349.  
  350.     /**
  351.      * If true show the linkURL in the status area when the mouse is over the button.
  352.      * If the linkURL is null, nothing is displayed, regardless of this flag.
  353.      * This flag also controls erasing of the status area after the URL has been displayed.
  354.      * @return true if the linkURL will be displayed in the status area when the mouse
  355.      * is over the button.
  356.      * @see #setShowURLStatus
  357.      */
  358.     public boolean isShowURLStatus()
  359.     {
  360.         return showURLStatus;
  361.     }
  362.  
  363.     /**
  364.      * Sets the current border color.
  365.      * @param color the new border color
  366.      * @exception PropertyVetoException
  367.      * if the specified property value is unacceptable
  368.      * @see #getBorderColor
  369.      */
  370.     public void setBorderColor(Color color) throws PropertyVetoException
  371.     {
  372.         if (!GeneralUtils.objectsEqual(borderColor, color))
  373.         {
  374.             Color oldValue = borderColor;
  375.  
  376.             vetos.fireVetoableChange("borderColor", oldValue, color);
  377.  
  378.             borderColor = color;
  379.             try
  380.             {
  381.                 disabledBorderColor    = ColorUtils.lighten(borderColor,    0.466);
  382.             }
  383.             catch (IllegalArgumentException exc) {}
  384.             repaint();
  385.  
  386.             changes.firePropertyChange("borderColor", oldValue, color);
  387.         }
  388.     }
  389.  
  390.     /**
  391.      * Gets the current border color.
  392.      * @return the current border color
  393.      * @see #setBorderColor
  394.      */
  395.     public Color getBorderColor()
  396.     {
  397.         return borderColor;
  398.     }
  399.  
  400.     /**
  401.      * Sets the current button color.
  402.      * @param color the new button color.  The highlights of the button are
  403.      * derived from this color.
  404.      * @exception PropertyVetoException
  405.      * if the specified property value is unacceptable
  406.      * @see #getButtonColor
  407.      */
  408.     public void setButtonColor(Color color) throws PropertyVetoException
  409.     {
  410.         if (!GeneralUtils.objectsEqual(buttonColor, color))
  411.         {
  412.             Color oldValue = buttonColor;
  413.  
  414.             vetos.fireVetoableChange("buttonColor", oldValue, color);
  415.             buttonColor = color;
  416.             try
  417.             {
  418.                 hilightColor            = ColorUtils.lighten(buttonColor,    0.600);
  419.                 pressedHilightColor        = ColorUtils.darken(buttonColor,    0.580);
  420.                 disabledHilightColor    = ColorUtils.lighten(buttonColor,    0.666);
  421.                 shadowColor                = ColorUtils.darken(buttonColor,    0.250);
  422.                 pressedShadowColor        = ColorUtils.darken(buttonColor,    0.100);
  423.                 disabledShadowColor        = ColorUtils.darken(buttonColor,    0.166);
  424.                 disabledButtonColor        = ColorUtils.lighten(buttonColor,    0.333);
  425.                 pressedButtonColor        = ColorUtils.darken(buttonColor,    0.250);
  426.             }
  427.             catch (IllegalArgumentException exc) {}
  428.             repaint();
  429.  
  430.             changes.firePropertyChange("buttonColor", oldValue, color);
  431.         }
  432.     }
  433.  
  434.     /**
  435.      * Gets the current button color.
  436.      * @return the current button color
  437.      * @see #setButtonColor
  438.      */
  439.     public Color getButtonColor()
  440.     {
  441.         return buttonColor;
  442.     }
  443.  
  444.     /**
  445.      * Sets the URL of the document to link to when the button is clicked.
  446.      * @param url the URL
  447.      * @exception java.beans.PropertyVetoException
  448.      * if the specified property value is unacceptable
  449.      * @see #getLinkURL
  450.      */
  451.     public void setLinkURL(URL url) throws PropertyVetoException
  452.     {
  453.         if(!GeneralUtils.objectsEqual(linkURL, url))
  454.         {
  455.             URL oldValue = linkURL;
  456.  
  457.             vetos.fireVetoableChange("linkURL", oldValue, url);
  458.  
  459.             linkURL = url;
  460.             context = null;
  461.  
  462.             changes.firePropertyChange("linkURL", oldValue, url);
  463.         }
  464.     }
  465.  
  466.     /**
  467.      * Returns the URL of the document to link to when the button is clicked.
  468.      * @see #setLinkURL
  469.      */
  470.     public URL getLinkURL()
  471.     {
  472.         return linkURL;
  473.     }
  474.  
  475.     /**
  476.      * Sets the frame specifier for showing a URL document in a browser or applet
  477.      * viewer. It is interpreted as follows:
  478.      * <UL>
  479.      * <DT>"_self"  show document in the current frame</DT>
  480.      * <DT>"_parent"    show document in the parent frame</DT>
  481.      * <DT>"_top"   show document in the topmost frame</DT>
  482.      * <DT>"_blank" show document in a new unnamed toplevel window</DT>
  483.      * <DT>all others   show document in a new toplevel window with the given name</DT>
  484.      * </UL>
  485.      * @param newFrame the frame specifier
  486.      * @exception java.beans.PropertyVetoException
  487.      * if the specified property value is unacceptable
  488.      * @see #getFrame
  489.      * @see symantec.itools.util.GeneralUtils#frameTarget_self
  490.      * @see symantec.itools.util.GeneralUtils#frameTarget_parent
  491.      * @see symantec.itools.util.GeneralUtils#frameTarget_top
  492.      * @see symantec.itools.util.GeneralUtils#frameTarget_blank
  493.      */
  494.     public void setFrame(String newFrame) throws PropertyVetoException
  495.     {
  496.         String oldValue = frame;
  497.  
  498.         vetos.fireVetoableChange("frame", oldValue, newFrame);
  499.  
  500.         frame = newFrame;
  501.  
  502.         changes.firePropertyChange("frame", oldValue, newFrame);
  503.     }
  504.  
  505.     /**
  506.      * Gets the frame specifier for showing a URL document in a browser or applet
  507.      * viewer. It is interpreted as follows:
  508.      * <UL>
  509.      * <DT>"_self"  show document in the current frame</DT>
  510.      * <DT>"_parent"    show document in the parent frame</DT>
  511.      * <DT>"_top"   show document in the topmost frame</DT>
  512.      * <DT>"_blank" show document in a new unnamed toplevel window</DT>
  513.      * <DT>all others   show document in a new toplevel window with the given name</DT>
  514.      * </UL>
  515.      * @return the frame specifier
  516.      * @see #setFrame
  517.      * @see symantec.itools.util.GeneralUtils#frameTarget_self
  518.      * @see symantec.itools.util.GeneralUtils#frameTarget_parent
  519.      * @see symantec.itools.util.GeneralUtils#frameTarget_top
  520.      * @see symantec.itools.util.GeneralUtils#frameTarget_blank
  521.      */
  522.     public String getFrame()
  523.     {
  524.         return frame;
  525.     }
  526.  
  527.     /**
  528.      * Ensures that this component is laid out properly, as needed.
  529.      * This is a standard Java AWT method which gets called by the AWT to
  530.      * make sure this component and its subcomponents have a valid layout.
  531.      * If this component was made invalid with a call to invalidate(), then
  532.      * it is laid out again.
  533.      *
  534.      * It is overridden here to locate the applet containing this component.
  535.      *
  536.      * @see java.awt.Component#invalidate
  537.      */
  538.     public void validate()
  539.     {
  540.         // On validation, try to find the containing applet.  If we can find
  541.         // it, we don't bother doing the link...
  542.         if (context == null)
  543.         {
  544.             Container c;
  545.  
  546.             c = getParent();
  547.  
  548.             while (c != null)
  549.             {
  550.                 if (c instanceof Applet)
  551.                 {
  552.                     setAppletContext(((Applet) c).getAppletContext());
  553.                     break;
  554.                 }
  555.  
  556.                 c = c.getParent();
  557.             }
  558.         }
  559.     }
  560.  
  561.     /**
  562.      * Enables this component so that it will respond to user input.
  563.      * This is a standard Java AWT method which gets called to enable or disable
  564.      * this component. Once enabled this component will respond to user input.
  565.      *
  566.      * @param flag true if the component is to be enabled; false if it is to be disabled.
  567.      * @see java.awt.Component#isEnabled
  568.      */
  569.     public void setEnabled(boolean flag)
  570.     {
  571.         if(isEnabled() != flag)
  572.         {
  573.             if(flag)
  574.             {
  575.                 // !!! LAB !!!    This MUST be a call to super.enable(), not super.enable(boolean)
  576.                 //                or super.setEnabled(boolean)  If it is not, then it will result
  577.                 //                in an endless loop!
  578.                 super.enable();
  579.                 pressed = false;
  580.                 pressedAdjustment = 0;
  581.             }
  582.             else
  583.             {
  584.                 // !!! LAB !!!    This MUST be a call to super.disable(), not super.enable(boolean)
  585.                 //                or super.setEnabled(boolean)  If it is not, then it will result
  586.                 //                in an endless loop!
  587.                 super.disable();
  588.                 if (notifyTimer != null)
  589.                 {
  590.                     notifyTimer.stop();
  591.                 }
  592.  
  593.                 pressed = false;
  594.                 pressedAdjustment = 0;
  595.             }
  596.  
  597.             repaint();
  598.         }
  599.     }
  600.  
  601.     /**
  602.      * @deprecated
  603.      * @see #setEnabled
  604.      */
  605.     public void enable()
  606.     {
  607.         setEnabled(true);
  608.     }
  609.  
  610.     /**
  611.      * @deprecated
  612.      * @see #setEnabled
  613.      */
  614.     public void disable()
  615.     {
  616.         setEnabled(false);
  617.     }
  618.  
  619.     /**
  620.      * Tells this component that it has been added to a container.
  621.      * This is a standard Java AWT method which gets called by the AWT when
  622.      * this component is added to a container. Typically, it is used to
  623.      * create this component's peer.
  624.      *
  625.      * It has been overridden here to hook-up event listeners.
  626.      *
  627.      * @see #removeNotify
  628.      */
  629.     public synchronized void addNotify()
  630.     {
  631.         try
  632.         {
  633.             errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  634.         }
  635.         catch(Throwable ex)
  636.         {
  637.             errors = new symantec.itools.resources.ErrorsBundle();
  638.         }
  639.  
  640.         //Hook up listeners
  641.         if (focus == null)
  642.         {
  643.             focus = new Focus();
  644.             addFocusListener(focus);
  645.         }
  646.         if (key == null)
  647.         {
  648.             key = new Key();
  649.             addKeyListener(key);
  650.         }
  651.         if (mouse == null)
  652.         {
  653.             mouse = new Mouse();
  654.             addMouseListener(mouse);
  655.         }
  656.         if (bevelVeto == null)
  657.         {
  658.             bevelVeto = new BevelVeto();
  659.             addBevelHeightListener(bevelVeto);
  660.         }
  661.         if (frameVeto == null)
  662.         {
  663.             frameVeto = new FrameVeto();
  664.             addFrameListener(frameVeto);
  665.         }
  666.         //Add after the listeners are hooked up
  667.         super.addNotify();
  668.  
  669.         isAdded = true;
  670.         verifyContstrainedPropertyValues();
  671.  
  672.         // On addNotify, try to find the containing applet.
  673.         if (context == null)
  674.         {
  675.             Container c;
  676.  
  677.             c = getParent();
  678.  
  679.             while (c != null)
  680.             {
  681.                 if (c instanceof Applet)
  682.                 {
  683.                     setAppletContext(((Applet) c).getAppletContext());
  684.                     break;
  685.                 }
  686.  
  687.                 c = c.getParent();
  688.             }
  689.         }
  690.     }
  691.  
  692.     /**
  693.      * Tells this component that it is being removed from a container.
  694.      * This is a standard Java AWT method which gets called by the AWT when
  695.      * this component is removed from a container. Typically, it is used to
  696.      * destroy the peers of this component and all its subcomponents.
  697.      *
  698.      * It has been overridden here to unhook event listeners.
  699.      *
  700.      * @see #addNotify
  701.      */
  702.     public synchronized void removeNotify()
  703.     {
  704.         //Unhook listeners
  705.         if (focus != null)
  706.         {
  707.             removeFocusListener(focus);
  708.             focus = null;
  709.         }
  710.         if (key != null)
  711.         {
  712.             removeKeyListener(key);
  713.             key = null;
  714.         }
  715.         if (mouse != null)
  716.         {
  717.             removeMouseListener(mouse);
  718.             mouse = null;
  719.         }
  720.         if (bevelVeto != null)
  721.         {
  722.             removeBevelHeightListener(bevelVeto);
  723.             bevelVeto = null;
  724.         }
  725.         if (frameVeto != null)
  726.         {
  727.             removeFrameListener(frameVeto);
  728.             frameVeto = null;
  729.         }
  730.  
  731.         super.removeNotify();
  732.         isAdded = false;
  733.     }
  734.  
  735.     /**
  736.      * Handles redrawing of this component on the screen.
  737.      * This is a standard Java AWT method which gets called by the Java
  738.      * AWT (repaint()) to handle repainting this component on the screen.
  739.      * The graphics context clipping region is set to the bounding rectangle
  740.      * of this component and its [0,0] coordinate is this component's
  741.      * top-left corner.
  742.      * Typically this method paints the background color to clear the
  743.      * component's drawing space, sets graphics context to be the foreground
  744.      * color, and then calls paint() to draw the component.
  745.      *
  746.      * It is overridden here to prevent the flicker associated with the standard
  747.      * update() method's repainting of the background before painting the component
  748.      * itself.
  749.      *
  750.      * @param g the graphics context
  751.      * @see java.awt.Component#repaint
  752.      * @see #paint
  753.      */
  754.     public void update(Graphics g)
  755.     {
  756.         paint(g);
  757.     }
  758.  
  759.     /**
  760.      * Paints this component using the given graphics context.
  761.      * This is a standard Java AWT method which typically gets called
  762.      * by the AWT to handle painting this component. It paints this component
  763.      * using the given graphics context. The graphics context clipping region
  764.      * is set to the bounding rectangle of this component and its [0,0]
  765.      * coordinate is this component's top-left corner.
  766.      *
  767.      * @param g the graphics context used for painting
  768.      * @see java.awt.Component#repaint
  769.      * @see #update
  770.      */
  771.     public void paint(Graphics g)
  772.     {
  773.         updateButtonImage();
  774.         g.drawImage(buttonImage, 0, 0, this);
  775.     }
  776.  
  777.     /**
  778.      * Returns the recommended dimensions to properly display this component.
  779.      * This is a standard Java AWT method which gets called to determine
  780.      * the recommended size of this component.
  781.      */
  782.     public Dimension getPreferredSize()
  783.     {
  784.         return new Dimension(bevel + bevel + 2, bevel + bevel + 2);
  785.     }
  786.  
  787.     /**
  788.      * @deprecated
  789.      * @see #getPreferredSize
  790.      */
  791.     public Dimension preferredSize()
  792.     {
  793.         return getPreferredSize();
  794.     }
  795.  
  796.     /**
  797.      * Returns the minimum dimensions to properly display this component.
  798.      * This is a standard Java AWT method which gets called to determine
  799.      * the minimum size of this component.
  800.      * It simply returns the results of a call to preferedSize().
  801.      */
  802.     public Dimension getMinimumSize()
  803.     {
  804.         return getPreferredSize();
  805.     }
  806.  
  807.     /**
  808.      * @deprecated
  809.      * @see #getMinimumSize
  810.      */
  811.     public Dimension minimumSize()
  812.     {
  813.         return getMinimumSize();
  814.     }
  815.  
  816.     public boolean isFocusTraversable()
  817.     {
  818.         return true;
  819.     }
  820.  
  821.     /**
  822.      * Makes the button act as if it was pressed, drawing
  823.      * as if it were clicked and sending an action event as if it
  824.      * were clicked.
  825.      */
  826.     public void simulateClick()
  827.     {
  828.         //pressed
  829.         requestFocus();
  830.         inButton    = true;
  831.         pressed        = true;
  832.         released    = false;
  833.         if(useOffset)
  834.             pressedAdjustment = bevel;
  835.         paint(getGraphics());
  836.  
  837.         //Wait for a bit
  838.         try { Thread.sleep(120); } catch (java.lang.InterruptedException exc) {}
  839.  
  840.         //released
  841.         inButton    = false;
  842.         pressed = false;
  843.         pressedAdjustment = 0;
  844.         linkToURL();
  845.         sourceActionEvent();
  846.         released = true;
  847.         repaint();
  848.     }
  849.  
  850.     /**
  851.      * Adds a listener for all event changes.
  852.      * @param listener the listener to add.
  853.      * @see #removePropertyChangeListener
  854.      */
  855.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  856.     {
  857.         changes.addPropertyChangeListener(listener);
  858.     }
  859.  
  860.     /**
  861.      * Removes a listener for all event changes.
  862.      * @param listener the listener to remove.
  863.      * @see #addPropertyChangeListener
  864.      */
  865.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  866.     {
  867.         changes.removePropertyChangeListener(listener);
  868.     }
  869.  
  870.     /**
  871.      * Adds a vetoable listener for all event changes.
  872.      * @param listener the listener to add.
  873.      * @see #removeVetoableChangeListener
  874.      */
  875.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  876.     {
  877.         vetos.addVetoableChangeListener(listener);
  878.     }
  879.  
  880.     /**
  881.      * Removes a vetoable listener for all event changes.
  882.      * @param listener the listener to remove.
  883.      * @see #addVetoableChangeListener
  884.      */
  885.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  886.     {
  887.         vetos.removeVetoableChangeListener(listener);
  888.     }
  889.  
  890.     /**
  891.      * Adds a listener for the BevelHeight property changes.
  892.      * @param listener the listener to add.
  893.      * @see #removeBevelHeightListener(java.beans.PropertyChangeListener)
  894.      */
  895.     public synchronized void addBevelHeightListener(PropertyChangeListener listener)
  896.     {
  897.         changes.addPropertyChangeListener("bevelHeight", listener);
  898.     }
  899.  
  900.     /**
  901.      * Removes a listener for the BevelHeight property changes.
  902.      * @param listener the listener to remove.
  903.      * @see #addBevelHeightListener(java.beans.PropertyChangeListener)
  904.      */
  905.     public synchronized void removeBevelHeightListener(PropertyChangeListener listener)
  906.     {
  907.         changes.removePropertyChangeListener("bevelHeight", listener);
  908.     }
  909.  
  910.     /**
  911.      * Adds a vetoable listener for the BevelHeight property changes.
  912.      * @param listener the listener to add.
  913.      * @see #removeBevelHeightListener(java.beans.VetoableChangeListener)
  914.      */
  915.     public synchronized void addBevelHeightListener(VetoableChangeListener listener)
  916.     {
  917.         vetos.addVetoableChangeListener("bevelHeight", listener);
  918.     }
  919.  
  920.     /**
  921.      * Removes a vetoable listener for the BevelHeight property changes.
  922.      * @param listener the listener to remove.
  923.      * @see #addBevelHeightListener(java.beans.VetoableChangeListener)
  924.      */
  925.     public synchronized void removeBevelHeightListener(VetoableChangeListener listener)
  926.     {
  927.         vetos.removeVetoableChangeListener("bevelHeight", listener);
  928.     }
  929.  
  930.     /**
  931.      * Adds a listener for the Frame property changes.
  932.      * @param listener the listener to add.
  933.      * @see #removeFrameListener(java.beans.PropertyChangeListener)
  934.      */
  935.     public synchronized void addFrameListener(PropertyChangeListener listener)
  936.     {
  937.         changes.addPropertyChangeListener("frame", listener);
  938.     }
  939.  
  940.     /**
  941.      * Removes a listener for the Frame property changes.
  942.      * @param listener the listener to remove.
  943.      * @see #addFrameListener(java.beans.PropertyChangeListener)
  944.      */
  945.     public synchronized void removeFrameListener(PropertyChangeListener listener)
  946.     {
  947.         changes.removePropertyChangeListener("frame", listener);
  948.     }
  949.  
  950.     /**
  951.      * Adds a vetoable listener for the Frame property changes.
  952.      * @param listener the listener to add.
  953.      * @see #removeFrameListener(java.beans.VetoableChangeListener)
  954.      */
  955.     public synchronized void addFrameListener(VetoableChangeListener listener)
  956.     {
  957.         vetos.addVetoableChangeListener("frame", listener);
  958.     }
  959.  
  960.     /**
  961.      * Removes a vetoable listener for the Frame property changes.
  962.      * @param listener the listener to remove.
  963.      * @see #addFrameListener(java.beans.VetoableChangeListener)
  964.      */
  965.     public synchronized void removeFrameListener(VetoableChangeListener listener)
  966.     {
  967.         vetos.removeVetoableChangeListener("frame", listener);
  968.     }
  969.  
  970.     /**
  971.      * Sets the command name of the action event fired by this button.
  972.      * @param command The name of the action event command fired by this button
  973.      * @exception PropertyVetoException
  974.      * if the specified property value is unacceptable
  975.      */
  976.     public void setActionCommand(String command) throws PropertyVetoException
  977.     {
  978.         String oldValue = actionCommand;
  979.  
  980.         vetos.fireVetoableChange("actionCommand", oldValue, command);
  981.         actionCommand = command;
  982.         changes.firePropertyChange("actionCommand", oldValue, command);
  983.     }
  984.  
  985.     /**
  986.      * Returns the command name of the action event fired by this button.
  987.      * @return the action command name
  988.      */
  989.     public String getActionCommand()
  990.     {
  991.         return actionCommand;
  992.     }
  993.  
  994.     /**
  995.      * Adds the specified action listener to receive action events
  996.      * from this button.
  997.      * @param l the action listener
  998.      */
  999.     public synchronized void addActionListener(ActionListener l)
  1000.     {
  1001.         actionListener = AWTEventMulticaster.add(actionListener, l);
  1002.     }
  1003.  
  1004.     /**
  1005.      * Removes the specified action listener so it no longer receives
  1006.      * action events from this button.
  1007.      * @param l the action listener
  1008.      */
  1009.     public synchronized void removeActionListener(ActionListener l)
  1010.     {
  1011.         actionListener = AWTEventMulticaster.remove(actionListener, l);
  1012.     }
  1013.  
  1014.     class Focus extends java.awt.event.FocusAdapter implements java.io.Serializable
  1015.     {
  1016.         public void focusGained(FocusEvent e)
  1017.         {
  1018.             hasFocus = true;
  1019.             repaint();
  1020.         }
  1021.  
  1022.         public void focusLost(FocusEvent e)
  1023.         {
  1024.             hasFocus = false;
  1025.             repaint();
  1026.         }
  1027.     }
  1028.  
  1029.     class Key extends java.awt.event.KeyAdapter implements java.io.Serializable
  1030.     {
  1031.         public void keyPressed(KeyEvent evt)
  1032.         {
  1033.             boolean isSpaceBar = (evt.getKeyCode() & KeyEvent.VK_SPACE) == KeyEvent.VK_SPACE;
  1034.  
  1035.             if(isSpaceBar && hasFocus && showFocus && !symantec.itools.lang.OS.isMacintosh()) {
  1036.             inButton = true;
  1037.             notified = false;
  1038.             if (notifyTimer != null && notifyWhilePressed && !running)
  1039.             {
  1040.                 running     = true;
  1041.                 notifyTimer.start();
  1042.             }
  1043.  
  1044.             pressed           = true;
  1045.             released          = false;
  1046.             if(useOffset)
  1047.                 pressedAdjustment = bevel;
  1048.             repaint();
  1049.             }
  1050.  
  1051.         }
  1052.         public void keyReleased(KeyEvent evt)
  1053.         {
  1054.             boolean isSpaceBar = (evt.getKeyCode() & KeyEvent.VK_SPACE) == KeyEvent.VK_SPACE;
  1055.  
  1056.             if(isSpaceBar && hasFocus && showFocus && !symantec.itools.lang.OS.isMacintosh()) {
  1057.             inButton = false;
  1058.             if (notifyTimer != null && running)
  1059.             {
  1060.                 running = false;
  1061.                 notifyTimer.stop();
  1062.             }
  1063.  
  1064.             if (pressed)
  1065.             {
  1066.                 pressed = false;
  1067.                 pressedAdjustment = 0;
  1068.  
  1069.                 if (!notifyWhilePressed || !notified)
  1070.                 {
  1071.                     //Handle going to the linkURL
  1072.                     linkToURL();
  1073.                     sourceActionEvent();
  1074.                 }
  1075.             }
  1076.  
  1077.             released = true;
  1078.             repaint();
  1079.             }
  1080.  
  1081.         }
  1082.     }
  1083.  
  1084.     /**
  1085.      * This is the Mouse Event handling innerclass.
  1086.      */
  1087.     class Mouse extends java.awt.event.MouseAdapter implements java.io.Serializable
  1088.     {
  1089.         /**
  1090.          * Handles the Mouse Pressed events
  1091.          * If the notifyWhilePressed flag is true the notification Timer is started
  1092.          * @param e the MouseEvent
  1093.          * @see #setNotifyWhilePressed
  1094.          * @see #setNotifyDelay
  1095.          * @see #mouseReleased
  1096.          */
  1097.         public void mousePressed(MouseEvent e)
  1098.         {
  1099.             requestFocus();
  1100.             notified = false;
  1101.             if (notifyTimer != null && notifyWhilePressed && !running)
  1102.             {
  1103.                 running     = true;
  1104.                 notifyTimer.start();
  1105.             }
  1106.  
  1107.             pressed           = true;
  1108.             released          = false;
  1109.             if(useOffset)
  1110.                 pressedAdjustment = bevel;
  1111.             repaint();
  1112.         }
  1113.  
  1114.         /**
  1115.          * Handles the Mouse Released events
  1116.          * If the notification timer is running it is stopped.
  1117.          * If the mouse was pressed inside the button then fire an action event.
  1118.          * @param e the MouseEvent
  1119.          * @see #mousePressed
  1120.          */
  1121.         public void mouseReleased(MouseEvent e)
  1122.         {
  1123.             if (notifyTimer != null && running)
  1124.             {
  1125.                 running = false;
  1126.                 notifyTimer.stop();
  1127.             }
  1128.  
  1129.             if (pressed)
  1130.             {
  1131.                 pressed = false;
  1132.                 pressedAdjustment = 0;
  1133.  
  1134.                 if (!notifyWhilePressed || !notified)
  1135.                 {
  1136.                     //Handle going to the linkURL
  1137.                     linkToURL();
  1138.                     sourceActionEvent();
  1139.                 }
  1140.             }
  1141.  
  1142.             released = true;
  1143.             if(inButton)
  1144.                 repaint();
  1145.         }
  1146.  
  1147.         /**
  1148.          * Handles Mouse Entered events
  1149.          * @param e the MouseEvent
  1150.          */
  1151.         public void mouseEntered(MouseEvent e)
  1152.         {
  1153.             inButton = true;
  1154.  
  1155.             //Display the linkURL
  1156.             if (showURLStatus && context != null && linkURL != null)
  1157.             {
  1158.                 context.showStatus(linkURL.toString());
  1159.             }
  1160.  
  1161.             if (!released)
  1162.             {
  1163.                 pressed = true;
  1164.                 if(useOffset)
  1165.                     pressedAdjustment = bevel;
  1166.  
  1167.                 if(notifyTimer != null && notifyWhilePressed && !running)
  1168.                 {
  1169.                     running = true;
  1170.                     notifyTimer.start();
  1171.                 }
  1172.                 repaint();
  1173.             }
  1174.         }
  1175.  
  1176.         /**
  1177.          * Handles Mouse Exited events
  1178.          * @param e the MouseEvent
  1179.          */
  1180.         public void mouseExited(MouseEvent e)
  1181.         {
  1182.             inButton = false;
  1183.  
  1184.             if (notifyTimer != null && running)
  1185.             {
  1186.                 running = false;
  1187.                 notifyTimer.stop();
  1188.             }
  1189.  
  1190.             if (pressed)
  1191.             {
  1192.                 pressed = false;
  1193.                 pressedAdjustment = 0;
  1194.                 repaint();
  1195.             }
  1196.  
  1197.             if (showURLStatus && context != null && linkURL != null)
  1198.             {
  1199.                 context.showStatus("");
  1200.             }
  1201.         }
  1202.     }
  1203.  
  1204.     /**
  1205.      * This is the Action Event handling innerclass.
  1206.      */
  1207.     class Action implements java.awt.event.ActionListener, java.io.Serializable
  1208.     {
  1209.         //Implement ActionListener to catch ActionEvents sent by either the notifyTimer.
  1210.         /**
  1211.          * Handles Action events
  1212.          * @param e the ActionEvent
  1213.          */
  1214.         public void actionPerformed(ActionEvent e)
  1215.         {
  1216.             if (e.getSource() == notifyTimer && notifyWhilePressed && !java.beans.Beans.isDesignTime())
  1217.             {
  1218.                 notified = true;
  1219.                 sourceActionEvent();
  1220.                 return;
  1221.             }
  1222.         }
  1223.     }
  1224.  
  1225.     /**
  1226.      * This is the PropertyChangeEvent handling inner class for the constrained BevelHeight property.
  1227.      * Handles vetoing BevelHeights that are not valid.
  1228.      */
  1229.     class BevelVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  1230.     {
  1231.         /**
  1232.          * This method gets called when an attempt to change the constrained BevelHeight property is made.
  1233.          * Ensures the given bevel size is valid for this button.
  1234.          *
  1235.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  1236.          *             event source and the property that has changed.
  1237.          * @exception PropertyVetoException if the recipient wishes the property
  1238.          *              change to be rolled back.
  1239.          */
  1240.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  1241.         {
  1242.             int i = ((Integer)e.getNewValue()).intValue();
  1243.             if (!isValidBevelSize(i))
  1244.             {
  1245.                 throw new PropertyVetoException(errors.getString("InvalidBevelSize") + i, e);
  1246.             }
  1247.         }
  1248.     }
  1249.  
  1250.     /**
  1251.      * This is the PropertyChangeEvent handling inner class for the constrained Frame property.
  1252.      * Handles vetoing Frame strings that are not valid.
  1253.      */
  1254.     class FrameVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  1255.     {
  1256.         /**
  1257.          * This method gets called when an attempt to change the constrained Frame property is made.
  1258.          * Ensures the given Frame string is valid for this button.
  1259.          *
  1260.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  1261.          *             event source and the property that has changed.
  1262.          * @exception PropertyVetoException if the recipient wishes the property
  1263.          *              change to be rolled back.
  1264.          */
  1265.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  1266.         {
  1267.             String string = (String)e.getNewValue();
  1268.             if (!isValidFrame(string))
  1269.             {
  1270.                 throw new PropertyVetoException(errors.getString("InvalidFrame") + string, e);
  1271.             }
  1272.         }
  1273.     }
  1274.  
  1275.     /**
  1276.      * Fire an action event to the listeners.
  1277.      */
  1278.     protected void sourceActionEvent()
  1279.     {
  1280.         if (actionListener != null)
  1281.             actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
  1282.     }
  1283.  
  1284.     /**
  1285.      * Is the given bevel size valid for this button.
  1286.      * @param i the given bevel size
  1287.      * @return true if the given bevel size is acceptable, false if not.
  1288.      */
  1289.     protected boolean isValidBevelSize(int i)
  1290.     {
  1291.         Dimension s = getSize();
  1292.  
  1293.         if (i < 0 || i >= (s.width / 2) || i >= (s.height / 2))
  1294.             return false;
  1295.         else
  1296.             return true;
  1297.     }
  1298.  
  1299.     /**
  1300.      * Is the given frame string valid.
  1301.      * @param string the given frame
  1302.      * @return true if the given frame is acceptable, false if not.
  1303.      * To be valid it has to be null, or one of the four strings below:
  1304.      * @see symantec.itools.util.GeneralUtils#frameTarget_self
  1305.      * @see symantec.itools.util.GeneralUtils#frameTarget_parent
  1306.      * @see symantec.itools.util.GeneralUtils#frameTarget_top
  1307.      * @see symantec.itools.util.GeneralUtils#frameTarget_blank
  1308.      */
  1309.     protected boolean isValidFrame(String string)
  1310.     {
  1311.         if(string == null || string.equals(""))
  1312.             return true;
  1313.  
  1314.         if(    string.equals(GeneralUtils.frameTarget_self)    ||
  1315.             string.equals(GeneralUtils.frameTarget_parent)    ||
  1316.             string.equals(GeneralUtils.frameTarget_top)        ||
  1317.             string.equals(GeneralUtils.frameTarget_blank)    )
  1318.             return true;
  1319.         else
  1320.             return false;
  1321.     }
  1322.  
  1323.     /**
  1324.      * Tell the browser to show the document referenced by the linkURL.
  1325.      * If the frame specifier is not null or empty, then tell the browser
  1326.      * to open the document with that frame.
  1327.      */
  1328.     protected void linkToURL()
  1329.     {
  1330.         if (context != null && linkURL != null)
  1331.         {
  1332.             if (frame == null || frame.length() == 0)
  1333.                 context.showDocument(linkURL);
  1334.             else
  1335.                 context.showDocument(linkURL, frame);
  1336.         }
  1337.     }
  1338.  
  1339.     /**
  1340.      * Called after addNotify to set the internally constrined properties to their
  1341.      * temporary values to validate them now that the component has been added to the form.
  1342.      * This is used to avoid code-gen order dependencies, since VC generates all property
  1343.      * manipulating code before adding the component to its container.
  1344.      * Subclasses should override this function for any internally constrained properties,
  1345.      * and call the super version in the overridden version.
  1346.      */
  1347.     protected void verifyContstrainedPropertyValues()
  1348.     {
  1349.         try { setBevelHeight(tempBevelHeight); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
  1350.     }
  1351.  
  1352.     /**
  1353.      * Sets the applet context used to view documents.
  1354.      * @param c the new applet context
  1355.      */
  1356.     protected void setAppletContext(AppletContext c)
  1357.     {
  1358.         context = c;
  1359.     }
  1360.  
  1361.     /**
  1362.      * Maintains the buttonImage size and draws the
  1363.      * button in the buttonImage offscreen image.
  1364.      * @see #paint
  1365.      */
  1366.     protected void updateButtonImage()
  1367.     {
  1368.         Dimension s    = getSize();
  1369.         int width    = s.width;
  1370.         int height    = s.height;
  1371.         int x        = bevel  + 1;
  1372.         int y        = bevel  + 1;
  1373.         int w        = width  - 1;
  1374.         int h        = height - 1;
  1375.         int i;
  1376.         Color highlight1, highlight2, fillColor, tempBorderColor;
  1377.         boolean raised = !(pressed && inButton);
  1378.  
  1379.         if(isButtonImageInvalid())
  1380.         {
  1381.             buttonImage = createImage(width, height);
  1382.             try
  1383.             {
  1384.                 MediaTracker tracker = new MediaTracker(this);
  1385.                 tracker.addImage(buttonImage, 0);
  1386.                 tracker.waitForID(0);
  1387.             }
  1388.             catch(InterruptedException e){}
  1389.         }
  1390.  
  1391.         buttonImageGraphics = buttonImage.getGraphics();
  1392.         Color oldColor = buttonImageGraphics.getColor();
  1393.  
  1394.         if(isEnabled())    //Enabled
  1395.         {
  1396.             tempBorderColor = borderColor;
  1397.  
  1398.             if (raised)
  1399.             {
  1400.                 fillColor    = buttonColor;
  1401.                 highlight1    = hilightColor;
  1402.                 highlight2    = shadowColor;
  1403.  
  1404.             }
  1405.             else    //Pressed
  1406.             {
  1407.                 fillColor    = pressedButtonColor;
  1408.                 highlight1    = pressedHilightColor;
  1409.                 highlight2    = pressedShadowColor;
  1410.  
  1411.             }
  1412.         }
  1413.         else //Disabled
  1414.         {
  1415.             tempBorderColor    = disabledBorderColor;
  1416.             fillColor        = disabledButtonColor;
  1417.             highlight1        = disabledHilightColor;
  1418.             highlight2        = disabledShadowColor;
  1419.         }
  1420.  
  1421.         if(!raised && useOffset)
  1422.         {
  1423.             //Fill the button content
  1424.             buttonImageGraphics.setColor(fillColor);
  1425.             buttonImageGraphics.fillRect(x, y, w - x, h - y);
  1426.  
  1427.             //Draw the bevels
  1428.             buttonImageGraphics.setColor(highlight1);
  1429.             for(i = 1; i <= bevel; i++)
  1430.             {
  1431.                 buttonImageGraphics.drawLine(i, i, i, h);
  1432.                 buttonImageGraphics.drawLine(i, i, w, i);
  1433.             }
  1434.         }
  1435.  
  1436.         if(raised || !useOffset)
  1437.         {
  1438.             //Fill the button content
  1439.             buttonImageGraphics.setColor(fillColor);
  1440.             buttonImageGraphics.fillRect(x, y, w - x, h - y);
  1441.  
  1442.             //Draw the bevels
  1443.             buttonImageGraphics.setColor(highlight1);
  1444.             for(i = 1; i <= bevel; i++)
  1445.             {
  1446.                 buttonImageGraphics.drawLine(i, i, i, h - i);
  1447.                 buttonImageGraphics.drawLine(i, i, w - i, i);
  1448.             }
  1449.             buttonImageGraphics.setColor(highlight2);
  1450.             for(i = 1; i <= bevel; ++i)
  1451.             {
  1452.                 buttonImageGraphics.drawLine(i, h - i, w - i, h - i);
  1453.                 buttonImageGraphics.drawLine(w - i, i, w - i, h - i);
  1454.             }
  1455.         }
  1456.  
  1457.         //Draw the border
  1458.         buttonImageGraphics.setColor(tempBorderColor);
  1459.         buttonImageGraphics.drawLine(1, 0, w - 1, 0);
  1460.         buttonImageGraphics.drawLine(0, 1, 0, h - 1);
  1461.         buttonImageGraphics.drawLine(1, h, w - 1, h);
  1462.         buttonImageGraphics.drawLine(w, h - 1, w, 1);
  1463.  
  1464.         if (hasFocus && showFocus) {
  1465.             buttonImageGraphics.setColor(java.awt.Color.darkGray);
  1466.             for(x = 3; x <= w - 3; x += 3)
  1467.                 buttonImageGraphics.drawLine(x, 3, x+1, 3);
  1468.             for(y = 3; y <= h - 3; y += 3)
  1469.                 buttonImageGraphics.drawLine(3, y, 3, y+1);
  1470.             for(x = 3; x <= w - 3; x += 3)
  1471.                 buttonImageGraphics.drawLine(x, h-3, x+1, h-3);
  1472.             for(y = 3; y <= h - 3; y += 3)
  1473.                 buttonImageGraphics.drawLine(w-3, y, w-3, y+1);
  1474.         }
  1475.  
  1476.  
  1477.         //!!! LAB !!! This should be changed to setClip when it works.
  1478.         //Set the clipping area to be the inside of the button.
  1479.         buttonImageGraphics.clipRect(bevel + 1, bevel + 1, width - bevel - bevel - 2, height - bevel - bevel - 2);
  1480.  
  1481.         //Restore the original color
  1482.         buttonImageGraphics.setColor(oldColor);
  1483.     }
  1484.  
  1485.     /**
  1486.      * Returns true if a button image has been set, but it is not the
  1487.      * size of this component.
  1488.      */
  1489.     protected boolean isButtonImageInvalid()
  1490.     {
  1491.         Dimension s = getSize();
  1492.         return (buttonImage == null || s.width     != buttonImage.getWidth(this) || s.height != buttonImage.getHeight(this));
  1493.     }
  1494.  
  1495.     /**
  1496.      * True if the button is currently pressed.
  1497.      */
  1498.     transient protected boolean   pressed;
  1499.     /**
  1500.      * True if the button has been released.
  1501.      */
  1502.     transient protected boolean   released;
  1503.     /**
  1504.      * True if the mouse is over this button.
  1505.      */
  1506.     transient protected boolean   inButton;
  1507.     /**
  1508.      * If true the button will continuously post events while pressed.
  1509.      */
  1510.     protected boolean   notifyWhilePressed;
  1511.     /**
  1512.      * True if the notify timer is running.
  1513.      */
  1514.     transient protected boolean   running;
  1515.     /**
  1516.      * True if a notification has been posted in response to a mouse down.
  1517.      */
  1518.     transient protected boolean   notified;
  1519.     /**
  1520.      * If true show the focus when the mouse enters the button.
  1521.      */
  1522.     protected boolean   showFocus = false;
  1523.     /**
  1524.      * If true set pressedAdjustment accordingly, else, it is always 0.
  1525.      */
  1526.     protected boolean   useOffset;
  1527.     /**
  1528.      * If true show the linkURL in the status area when the mouse is over the button.
  1529.      * If the linkURL is null, nothing is displayed, regardless of this flag.
  1530.      * This flag also controls erasing of the status area after the URL has been displayed.
  1531.      */
  1532.     protected boolean   showURLStatus;
  1533.     /**
  1534.      * Keeps track of wheather or not the button is added to a container.
  1535.      * Check before attempting to getFontMetrics() to avoid getting a null pointer.
  1536.      */
  1537.     transient protected boolean   isAdded;
  1538.     /**
  1539.      * The "height" (cross-section) of a beveled edge, in pixels.
  1540.      */
  1541.     protected int bevel;
  1542.     protected int tempBevelHeight;
  1543.     /**
  1544.      * The delay in milliseconds between notifications while the button is pressed.
  1545.      */
  1546.     protected int       notifyDelay;
  1547.     /**
  1548.      * A drawing location adjustment for the 3-D bevel while button is pressed.
  1549.      */
  1550.     protected int       pressedAdjustment;
  1551.     /**
  1552.      * Frame specifier for showing a URL document in a browser or applet
  1553.      * viewer. It is interpreted as follows:
  1554.      * <UL>
  1555.      * <DT>"_self"  show document in the current frame</DT>
  1556.      * <DT>"_parent"    show document in the parent frame</DT>
  1557.      * <DT>"_top"   show document in the topmost frame</DT>
  1558.      * <DT>"_blank" show document in a new unnamed toplevel window</DT>
  1559.      * <DT>all others   show document in a new toplevel window with the given name</DT>
  1560.      * </UL>
  1561.      */
  1562.     protected String    frame = null;
  1563.     /**
  1564.      * The color of the border around the button.
  1565.      */
  1566.     protected Color    borderColor;
  1567.     /**
  1568.      * The color of the content of the button.  The highlights are derived from this color.
  1569.      */
  1570.     protected Color    buttonColor;
  1571.     /**
  1572.      * Timer used to time notification events while button pressed.
  1573.      */
  1574.     protected Timer    notifyTimer;
  1575.     /**
  1576.      *    The offscreen buffer to draw the button in.
  1577.      */
  1578.     transient protected Image    buttonImage = null;
  1579.     /**
  1580.      *    The Graphics of the offscreen buffer to draw the button in.
  1581.      */
  1582.     transient protected Graphics    buttonImageGraphics = null;
  1583.     /**
  1584.      * The URL of the document to show when the button is clicked.
  1585.      */
  1586.     protected URL    linkURL = null;
  1587.     /**
  1588.      * Applet context that shows the document.
  1589.      */
  1590.     transient protected AppletContext context = null;
  1591.     transient protected ResourceBundle errors;
  1592.  
  1593.     String actionCommand;
  1594.     ActionListener actionListener = null;
  1595.     transient boolean hasFocus = false;
  1596.  
  1597.     private Color hilightColor            = null;
  1598.     private Color pressedHilightColor    = null;
  1599.     private Color disabledHilightColor    = null;
  1600.     private Color shadowColor            = null;
  1601.     private Color pressedShadowColor    = null;
  1602.     private Color disabledShadowColor    = null;
  1603.     private Color disabledBorderColor    = null;
  1604.     private Color disabledButtonColor    = null;
  1605.     private Color pressedButtonColor    = null;
  1606.     private Key key = null;
  1607.     private Focus focus = null;
  1608.     private Action    action        = new Action();
  1609.     private Mouse        mouse        = null;
  1610.     private BevelVeto    bevelVeto    = null;
  1611.     private FrameVeto    frameVeto    = null;
  1612.     private symantec.itools.beans.VetoableChangeSupport vetos = new symantec.itools.beans.VetoableChangeSupport(this);
  1613.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  1614. }
  1615.