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