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

  1. /*
  2.  * @(#)AbstractButton.java    1.73 98/02/03
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20. package com.sun.java.swing;
  21.  
  22. import java.awt.*;
  23. import java.awt.event.*;
  24. import java.awt.image.*;
  25. import java.io.Serializable;
  26. import com.sun.java.swing.event.*;
  27. import com.sun.java.swing.border.*;
  28. import com.sun.java.swing.plaf.*;
  29. import com.sun.java.accessibility.*;
  30.  
  31. /**
  32.  * Defines the common behaviors for the JButton, JToggleButton, JCheckbox,
  33.  * and the JRadioButton classes.
  34.  * <p>
  35.  * Warning: serialized objects of this class will not be compatible with
  36.  * future swing releases.  The current serialization support is appropriate 
  37.  * for short term storage or RMI between Swing1.0 applications.  It will
  38.  * not be possible to load serialized Swing1.0 objects with future releases
  39.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  40.  * baseline for the serialized form of Swing objects.
  41.  *
  42.  * @version 1.73 02/03/98
  43.  * @author Jeff Dinkins
  44.  */
  45. public abstract class AbstractButton extends JComponent implements ItemSelectable, SwingConstants {
  46.  
  47.     protected ButtonModel model                = null;  
  48.  
  49.     private String     text                    = ""; // for BeanBox
  50.     private Insets     margin                  = null;
  51.  
  52.     // Button icons
  53.     // PENDING(jeff) - hold icons in an array
  54.     private Icon       defaultIcon             = null;
  55.     private Icon       pressedIcon             = null;
  56.     private Icon       disabledIcon            = null;
  57.  
  58.     private Icon       selectedIcon            = null;
  59.     private Icon       disabledSelectedIcon    = null;
  60.  
  61.     private Icon       rolloverIcon            = null;
  62.     private Icon       rolloverSelectedIcon    = null;
  63.     
  64.     // Display properties
  65.     private boolean    paintBorder             = true;  
  66.     private boolean    paintFocus              = true;   
  67.     private boolean    rolloverEnabled         = false;   
  68.  
  69.     // Icon/Label Alignment
  70.     private int        verticalAlignment       = CENTER;
  71.     private int        horizontalAlignment     = CENTER;
  72.     
  73.     private int        verticalTextPosition    = CENTER;
  74.     private int        horizontalTextPosition  = RIGHT;
  75.  
  76.  
  77.     /**
  78.      * The button's model listeners.
  79.      */
  80.     protected ChangeListener changeListener = null;
  81.     protected ActionListener actionListener = null;
  82.     protected ItemListener itemListener = null;
  83.  
  84.     /**
  85.      * Only one ChangeEvent is needed per button instance since the
  86.      * event's only state is the source property.  The source of events
  87.      * generated is always "this".
  88.      */
  89.     protected transient ChangeEvent changeEvent;
  90.     
  91.     /**
  92.      * Returns the button's text.
  93.      * @see setText
  94.      */
  95.     public String getText() {
  96.     return text;
  97.     }
  98.     
  99.     /**
  100.      * Sets the button's text.
  101.      * @param t the string used to set the text
  102.      * @see getText
  103.      * @beaninfo
  104.      *        bound: true
  105.      *  description: The button's text.
  106.      */
  107.     public void setText(String text) {
  108.     String oldValue = text;
  109.     this.text = text;
  110.     firePropertyChange("text", oldValue, text);
  111.     if (accessibleContext != null) {
  112.         accessibleContext.firePropertyChange(
  113.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  114.         oldValue, text);
  115.     }
  116.         invalidate();
  117.     repaint();
  118.     }
  119.  
  120.     /**
  121.      * Returns the state of the button. True if the
  122.      * toggle button is selected, false if it's not.
  123.      */
  124.     public boolean isSelected() {
  125.         return model.isSelected();
  126.     }
  127.  
  128.     /**
  129.      * Sets the state of the button.
  130.      */
  131.     public void setSelected(boolean b) {
  132.     boolean oldValue = isSelected();
  133.     if (accessibleContext != null && oldValue != b) {
  134.         if (b) {
  135.         accessibleContext.firePropertyChange(
  136.             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  137.             null, AccessibleState.SELECTED);
  138.         } else {
  139.         accessibleContext.firePropertyChange(
  140.             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  141.             AccessibleState.SELECTED, null);
  142.         }
  143.     }
  144.         model.setSelected(b);
  145.     }
  146.  
  147.     /**
  148.      * Programatically perform a "click". This does the same
  149.      * thing as if the user had pressed and released the button.
  150.      */
  151.     public void doClick() {
  152.     doClick(68);
  153.     }
  154.  
  155.     /**
  156.      * Programatically perform a "click". This does the same
  157.      * thing as if the user had pressed and released the button.
  158.      * The button stays visually "pressed" for pressTime milliseconds.
  159.      */
  160.     public void doClick(int pressTime) {
  161.     Dimension size = getSize();
  162.     model.setArmed(true);
  163.     model.setPressed(true);
  164.     paintImmediately(new Rectangle(0,0, size.width, size.height));
  165.     try {
  166.         Thread.currentThread().sleep(pressTime);
  167.     } catch(InterruptedException ie) {
  168.     }
  169.     model.setPressed(false);
  170.     model.setArmed(false);
  171.     }
  172.  
  173.     /**
  174.      * Sets space for margin between the button's border and
  175.      * the label. Setting to null will cause the button to
  176.      * use the default margin.  The button's default Border
  177.      * object will use this value to create the proper margin.
  178.      * However, if a non-default border is set on the button, 
  179.      * it is that Border object's responsibility to create the
  180.      * appropriate margin space (else this property will
  181.      * effectively be ignored).
  182.      *
  183.      * @param m the space between the border and the label
  184.      *
  185.      * @beaninfo
  186.      *        bound: true
  187.      *  description: The space between the button's border and the label.
  188.      */
  189.     public void setMargin(Insets m) {
  190.         Insets old = margin;
  191.     margin = m;
  192.         firePropertyChange("margin", old, m);
  193.     invalidate();
  194.     }
  195.  
  196.     /**
  197.      * Returns the margin between the button's border and
  198.      * the label.
  199.      */
  200.     public Insets getMargin() {
  201.     if(margin == null) {
  202.         return ((ButtonUI)ui).getDefaultMargin(this);
  203.     } else {
  204.         return margin;
  205.     }
  206.     }
  207.  
  208.     /**
  209.      * Returns the default icon.
  210.      * @see setIcon
  211.      */
  212.     public Icon getIcon() {
  213.     return defaultIcon;
  214.     }
  215.     
  216.     /**
  217.      * Sets the button's default icon. This icon is
  218.      * also used as the "pressed" and "disabled" icon if
  219.      * there is no explicitly set pressed icon.
  220.      * @param g the icon used as the default image
  221.      * @see getIcon
  222.      * @see setPressedIcon
  223.      * @beaninfo 
  224.      *     bound: true
  225.      *     description: The button's default icon
  226.      */
  227.     public void setIcon(Icon defaultIcon) {
  228.     Icon oldValue = this.defaultIcon;
  229.     this.defaultIcon = defaultIcon;
  230.     firePropertyChange("icon", oldValue, defaultIcon);
  231.     if (accessibleContext != null) {
  232.         accessibleContext.firePropertyChange(
  233.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  234.         oldValue, defaultIcon);
  235.     }
  236.     invalidate();
  237.     repaint();
  238.     }
  239.     
  240.     /**
  241.      * Returns the pressed icon for the button.
  242.      * @see setPressedIcon
  243.      */
  244.     public Icon getPressedIcon() {
  245.     return pressedIcon;
  246.     }
  247.     
  248.     /**
  249.      * Sets the pressed icon for the button.
  250.      * @param g the icon used as the "pressed" image
  251.      * @see getPressedIcon
  252.      * @beaninfo
  253.      *        bound: true
  254.      *  description: The pressed icon for the button.
  255.      */
  256.     public void setPressedIcon(Icon pressedIcon) {
  257.     Icon oldValue = this.pressedIcon;
  258.     this.pressedIcon = pressedIcon;
  259.     firePropertyChange("pressedIcon", oldValue, pressedIcon);
  260.     if (accessibleContext != null) {
  261.         accessibleContext.firePropertyChange(
  262.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  263.         oldValue, defaultIcon);
  264.     }
  265.     invalidate();
  266.     repaint();
  267.     }
  268.  
  269.     /**
  270.      * Returns the selected icon for the button.
  271.      * @see setSelectedIcon
  272.      */
  273.     public Icon getSelectedIcon() {
  274.     return selectedIcon;
  275.     }
  276.     
  277.     /**
  278.      * Sets the selected icon for the button.
  279.      * @param g the icon used as the "selected" image
  280.      * @see getSelectedIcon
  281.      * @beaninfo
  282.      *        bound: true
  283.      *  description: The selected icon for the button.
  284.      */
  285.     public void setSelectedIcon(Icon selectedIcon) {
  286.     Icon oldValue = this.selectedIcon;
  287.     this.selectedIcon = selectedIcon;
  288.     firePropertyChange("selectedIcon", oldValue, selectedIcon);
  289.     if (accessibleContext != null) {
  290.         accessibleContext.firePropertyChange(
  291.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  292.         oldValue, selectedIcon);
  293.     }
  294.     invalidate();
  295.     repaint();
  296.     }
  297.  
  298.     /**
  299.      * Returns the rollover icon for the button.
  300.      * @see setRolloverIcon
  301.      */
  302.     public Icon getRolloverIcon() {
  303.     return rolloverIcon;
  304.     }
  305.     
  306.     /**
  307.      * Sets the rollover icon for the button.
  308.      * @param g the icon used as the "rollover" image
  309.      * @see getRolloverIcon
  310.      * @beaninfo
  311.      *        bound: true
  312.      *  description: The rollover icon for the button.
  313.      */
  314.     public void setRolloverIcon(Icon rolloverIcon) {
  315.     Icon oldValue = this.rolloverIcon;
  316.     this.rolloverIcon = rolloverIcon;
  317.     firePropertyChange("rolloverIcon", oldValue, rolloverIcon);
  318.     if (accessibleContext != null) {
  319.         accessibleContext.firePropertyChange(
  320.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  321.         oldValue, rolloverIcon);
  322.     }
  323.     setRolloverEnabled(true);
  324.     invalidate();
  325.     repaint();
  326.     }
  327.     
  328.     /**
  329.      * Returns the rollover seletion icon for the button.
  330.      * @see setRolloverSelectedIcon
  331.      */
  332.     public Icon getRolloverSelectedIcon() {
  333.     return rolloverSelectedIcon;
  334.     }
  335.     
  336.     /**
  337.      * Sets the rollover selected icon for the button.
  338.      * @param g the icon used as the "selected rollover" image
  339.      * @see getRolloverSelectedIcon
  340.      * @beaninfo
  341.      *        bound: true
  342.      *  description: The rollover selected icon for the button.
  343.      */
  344.     public void setRolloverSelectedIcon(Icon rolloverSelectedIcon) {
  345.     Icon oldValue = this.rolloverSelectedIcon;
  346.     this.rolloverSelectedIcon = rolloverSelectedIcon;
  347.     firePropertyChange("rolloverSelectedIcon", oldValue, rolloverSelectedIcon);
  348.     if (accessibleContext != null) {
  349.         accessibleContext.firePropertyChange(
  350.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  351.         oldValue, rolloverSelectedIcon);
  352.     }
  353.     invalidate();
  354.     repaint();
  355.     }
  356.     
  357.     /**
  358.      * Returns the icon used by the button when it's disabled.
  359.      * If not no disabled icon has been set, the button constructs
  360.      * one from the default icon. 
  361.      * PENDING(jeff): the disabled icon really should be created 
  362.      * (if necesary) by the L&F.
  363.      * @see getPressedIcon
  364.      * @see setDisabledIcon
  365.      */
  366.     public Icon getDisabledIcon() {
  367.     if(disabledIcon == null) {
  368.         if(defaultIcon != null
  369.            && defaultIcon instanceof ImageIcon) {
  370.         disabledIcon = new ImageIcon(
  371.             GrayFilter.createDisabledImage(
  372.             ((ImageIcon)defaultIcon).getImage()));
  373.         }
  374.     }
  375.     return disabledIcon;
  376.     }
  377.     
  378.     /**
  379.      * Sets the disabled icon for the button.
  380.      * @param g the icon used as the disabled image
  381.      * @see getDisabledIcon
  382.      * @beaninfo
  383.      *        bound: true
  384.      *  description: The disabled icon for the button.
  385.      */
  386.     public void setDisabledIcon(Icon disabledIcon) {
  387.     Icon oldValue = this.disabledIcon;
  388.     this.disabledIcon = disabledIcon;
  389.     firePropertyChange("disabledIcon", oldValue, disabledIcon);
  390.     if (accessibleContext != null) {
  391.         accessibleContext.firePropertyChange(
  392.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  393.         oldValue, disabledIcon);
  394.     }
  395.     invalidate();
  396.     repaint();
  397.     }
  398.     
  399.     /**
  400.      * Returns the icon used by the button when it's disabled and selected.
  401.      * If not no disabled selection icon has been set, the button constructs
  402.      * one from the selection icon. 
  403.      * PENDING(jeff): the disabled selection icon really should be created 
  404.      * (if necesary) by the L&F.
  405.      * @see getPressedIcon
  406.      * @see setDisabledIcon
  407.      */
  408.     public Icon getDisabledSelectedIcon() {
  409.     if(disabledSelectedIcon == null) {
  410.         if(selectedIcon != null && selectedIcon instanceof ImageIcon) {
  411.         disabledSelectedIcon = new ImageIcon(
  412.             GrayFilter.createDisabledImage(((ImageIcon)selectedIcon).getImage()));
  413.         } else {
  414.         return disabledIcon;
  415.         }
  416.     }
  417.     return disabledSelectedIcon;
  418.     }
  419.  
  420.     /**
  421.      * Sets the disabled selection icon for the button.
  422.      * @param g the icon used as the disabled selection image
  423.      * @see getDisabledSelectedIcon
  424.      */
  425.     public void setDisabledSelectedIcon(Icon disabledSelectedIcon) {
  426.     Icon oldValue = this.disabledSelectedIcon;
  427.     this.disabledSelectedIcon = disabledSelectedIcon;
  428.     firePropertyChange("disabledSelectedIcon", oldValue, disabledSelectedIcon);
  429.     if (accessibleContext != null) {
  430.         accessibleContext.firePropertyChange(
  431.         AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  432.         oldValue, disabledSelectedIcon);
  433.     }
  434.     invalidate();
  435.     repaint();
  436.     }
  437.  
  438.     /**
  439.      * Returns the vertical alignment of the text and icon.
  440.      * Valid keys: CENTER (the default), TOP, BOTTOM
  441.      */
  442.     public int getVerticalAlignment() {
  443.     return verticalAlignment;
  444.     }
  445.     
  446.     /**
  447.      * Sets the vertical alignment of the icon and text.
  448.      * Valid keys: CENTER (the default), TOP, BOTTOM
  449.      * @beaninfo
  450.      *        bound: true
  451.      *  description: The vertical alignment of the icon and text.
  452.      */
  453.     public void setVerticalAlignment(int alignment) {
  454.     if (alignment == verticalAlignment) return;
  455.     int oldValue = verticalAlignment;
  456.     verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
  457.     firePropertyChange("verticalAlignment", oldValue, verticalAlignment);    
  458.     invalidate();
  459.     repaint();
  460.     }
  461.     
  462.     /**
  463.      * Returns the horizontal alignment of the icon and text.
  464.      * Valid keys: CENTER (the default), LEFT, RIGHT
  465.      */
  466.     public int getHorizontalAlignment() {
  467.     return horizontalAlignment;
  468.     }
  469.     
  470.     /**
  471.      * Sets the horizontal alignment of the icon and text.
  472.      * Valid keys: CENTER (the default), LEFT, RIGHT
  473.      * @beaninfo
  474.      *        bound: true
  475.      *  description: The horizontal alignment of the icon and text.
  476.      */
  477.     public void setHorizontalAlignment(int alignment) {
  478.     if (alignment == horizontalAlignment) return;
  479.     int oldValue = horizontalAlignment;
  480.     horizontalAlignment = checkHorizontalKey(alignment, "horizontalAlignment");
  481.     firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);    
  482.     invalidate();
  483.     repaint();
  484.     }
  485.  
  486.     
  487.     /**
  488.      * Returns the vertical position of the text relative to the icon
  489.      * Valid keys: CENTER (the default), TOP, BOTTOM
  490.      */
  491.     public int getVerticalTextPosition() {
  492.     return verticalTextPosition;
  493.     }
  494.     
  495.     /**
  496.      * Sets the vertical position of the text relative to the icon.
  497.      * Valid keys: CENTER (the default), TOP, BOTTOM
  498.      * @beaninfo
  499.      *        bound: true
  500.      *  description: The vertical position of the text relative to the icon.
  501.      */
  502.     public void setVerticalTextPosition(int textPosition) {
  503.     if (textPosition == verticalTextPosition) return;
  504.     int oldValue = verticalTextPosition;
  505.     verticalTextPosition = checkVerticalKey(textPosition, "verticalTextPosition");
  506.     firePropertyChange("verticalTextPosition", oldValue, verticalTextPosition);
  507.     invalidate();
  508.     repaint();
  509.     }
  510.     
  511.     /**
  512.      * Sets the horizontal position of the text relative to the icon.
  513.      * Valid keys: RIGHT (the default), LEFT, CENTER
  514.      */
  515.     public int getHorizontalTextPosition() {
  516.     return horizontalTextPosition;
  517.     }
  518.     
  519.     /**
  520.      * Sets the horizontal position of the text relative to the icon.
  521.      * Valid keys: RIGHT (the default), LEFT, CENTER
  522.      * @beaninfo
  523.      *        bound: true
  524.      *  description: The horizontal position of the text relative to the icon.
  525.      */
  526.     public void setHorizontalTextPosition(int textPosition) {
  527.     if (textPosition == horizontalTextPosition) return;
  528.     int oldValue = horizontalTextPosition;
  529.     horizontalTextPosition = checkHorizontalKey(textPosition, "horizontalTextPosition");
  530.     firePropertyChange("horizontalTextPosition", oldValue, horizontalTextPosition);
  531.     invalidate();
  532.     repaint();
  533.     }
  534.     
  535.     /**
  536.      * Ensures that the key is a valid. Throws an IllegalArgument exception
  537.      * exception otherwise.
  538.      */
  539.     protected int checkHorizontalKey(int key, String exception) {
  540.     if ((key == LEFT) || (key == CENTER) || (key == RIGHT)) {
  541.         return key;
  542.     } else {
  543.         throw new IllegalArgumentException(exception);
  544.     }
  545.     }
  546.     
  547.     /**
  548.      * Ensures that the key is a valid. Throws an IllegalArgument exception
  549.      * exception otherwise.
  550.      */
  551.     protected int checkVerticalKey(int key, String exception) {
  552.     if ((key == TOP) || (key == CENTER) || (key == BOTTOM)) {
  553.         return key;
  554.     } else {
  555.         throw new IllegalArgumentException(exception);
  556.     }
  557.     }
  558.     
  559.     /**
  560.      * Sets the action command for this button. 
  561.      */
  562.     public void setActionCommand(String actionCommand) {
  563.     getModel().setActionCommand(actionCommand);
  564.     }
  565.     
  566.     /**
  567.      * Returns the action command for this button. 
  568.      */
  569.     public String getActionCommand() {
  570.     String ac = getModel().getActionCommand();
  571.     if(ac == null) {
  572.         ac = getText();
  573.     }
  574.     return ac;
  575.     }
  576.     
  577.     /**
  578.      * Returns whether the border should be painted.
  579.      * @see setBorderPainted
  580.      */
  581.     public boolean isBorderPainted() {
  582.     return paintBorder;
  583.     }
  584.     
  585.     /**
  586.      * Sets whether the border should be painted.
  587.      * @param b if true and border property is not null, the border is painted.
  588.      * @see isBorderPainted
  589.      * @beaninfo
  590.      *        bound: true
  591.      *  description: Whether the border should be painted.
  592.      */
  593.     public void setBorderPainted(boolean b) {
  594.     boolean oldValue = paintBorder;
  595.     paintBorder = b;
  596.     firePropertyChange("borderPainted", oldValue, paintBorder);
  597.     invalidate();
  598.     repaint();
  599.     }
  600.  
  601.     /**
  602.      * Paint the button's border if BorderPainted property is true.
  603.      * 
  604.      * @see #paint
  605.      * @see #setBorder
  606.      */
  607.     protected void paintBorder(Graphics g) {    
  608.         if (isBorderPainted()) {
  609.             super.paintBorder(g);
  610.         }
  611.     }
  612.  
  613.     /**
  614.      * Returns whether focus should be painted.
  615.      * @see setFocusPainted
  616.      */
  617.     public boolean isFocusPainted() {
  618.     return paintFocus;
  619.     }
  620.     
  621.     /**
  622.      * Sets whether focus should be painted.
  623.      * @param b if true, the focus state is painted.
  624.      * @see isFocusPainted
  625.      * @beaninfo
  626.      *        bound: true
  627.      *  description: Whether focus should be painted
  628.      */
  629.     public void setFocusPainted(boolean b) {
  630.     boolean oldValue = paintFocus;
  631.     paintFocus = b;
  632.     firePropertyChange("focusPainted", oldValue, paintFocus);
  633.     invalidate();
  634.     repaint();
  635.     }
  636.  
  637.     /**
  638.      * Checks whether rollover effects are enabled.
  639.      * @see setFocusPainted
  640.      */
  641.     public boolean isRolloverEnabled() {
  642.     return rolloverEnabled;
  643.     }
  644.     
  645.     /**
  646.      * Sets whether rollover effects should be enabled.
  647.      * @param b if true, rollover effects should be painted.
  648.      * @see isRolloverEnabled
  649.      * @beaninfo
  650.      *        bound: true
  651.      *  description: Whether rollover effects should be enabled.
  652.      */
  653.     public void setRolloverEnabled(boolean b) {
  654.     boolean oldValue = rolloverEnabled;
  655.     rolloverEnabled = b;
  656.     firePropertyChange("rolloverEnabled", oldValue, rolloverEnabled);
  657.     invalidate();
  658.     repaint();
  659.     }
  660.  
  661.  
  662.     /**
  663.      * Convenience to get the keyboard mnemonic from the the current model 
  664.      */
  665.     public int getMnemonic() {
  666.         return model.getMnemonic();
  667.     }
  668.  
  669.     /**
  670.      * Convenience to set the keyboard mnemonic on the current model
  671.      * @param mnemonic the key code which represents the mnemonic
  672.      */
  673.     public void setMnemonic(int mnemonic) {
  674.         model.setMnemonic(mnemonic);
  675.     invalidate();
  676.     repaint();
  677.     }
  678.  
  679.     public void setMnemonic(char mnemonic) {
  680.         int vk = (int) mnemonic;
  681.         if(vk >= 'a' && vk <='z')
  682.             vk -= ('a' - 'A');
  683.         setMnemonic(vk);
  684.     }
  685.  
  686.     /**
  687.      * Get the model that this button represents.
  688.      * @see setModel
  689.      */
  690.     public ButtonModel getModel() {
  691.     return model;
  692.     }
  693.     
  694.     /**
  695.      * Set the model that this button represents.
  696.      * @param m the Model
  697.      * @see getModel
  698.      * @beaninfo
  699.      *        bound: true
  700.      *  description: Model that the Button uses.
  701.      */
  702.     public void setModel(ButtonModel newModel) {
  703.     
  704.     ButtonModel oldModel = getModel();
  705.     
  706.     if (oldModel != null) {
  707.         oldModel.removeChangeListener(changeListener);
  708.         oldModel.removeActionListener(actionListener);
  709.         changeListener = null;
  710.         actionListener = null;
  711.     }
  712.     
  713.     model = newModel;
  714.     
  715.     if (newModel != null) {
  716.         changeListener = createChangeListener();
  717.         actionListener = createActionListener();
  718.         itemListener = createItemListener();
  719.         newModel.addChangeListener(changeListener);
  720.         newModel.addActionListener(actionListener);
  721.         newModel.addItemListener(itemListener);
  722.     }
  723.  
  724.     firePropertyChange("model", oldModel, newModel);
  725.     invalidate();
  726.     repaint();
  727.     }
  728.  
  729.     
  730.     /**
  731.      * Returns the button's current UI.
  732.      * @see setUI
  733.      */
  734.     public ButtonUI getUI() {
  735.     return (ButtonUI) ui;
  736.     }
  737.  
  738.     
  739.     /**
  740.      * Sets the button's UI.
  741.      * @param ui the new ButtonUI
  742.      * @see getUI
  743.      */
  744.     public void setUI(ButtonUI ui) {
  745.     super.setUI(ui);
  746.     }
  747.  
  748.     
  749.     /**
  750.      * Gets a new UI object from the default UIFactory. Subtypes of
  751.      * AbstractButton should override this to update the UI. For
  752.      * example, JButton might do the following:
  753.      *      setUI((ButtonUI)UIManager.getUI(
  754.      *          "ButtonUI", "com.sun.java.swing.plaf.basic.BasicButtonUI", this));
  755.      */
  756.     public void updateUI() {
  757.     }
  758.     
  759.     /**
  760.      * Adds a ChangeListener to the button.
  761.      */
  762.     public void addChangeListener(ChangeListener l) {
  763.     listenerList.add(ChangeListener.class, l);
  764.     }
  765.     
  766.     /**
  767.      * Removes a ChangeListener from the button.
  768.      */
  769.     public void removeChangeListener(ChangeListener l) {
  770.     listenerList.remove(ChangeListener.class, l);
  771.     }
  772.     
  773.     /*
  774.      * Notify all listeners that have registered interest for
  775.      * notification on this event type.  The event instance 
  776.      * is lazily created using the parameters passed into 
  777.      * the fire method.
  778.      * @see EventListenerList
  779.      */
  780.     protected void fireStateChanged() {
  781.     // Guaranteed to return a non-null array
  782.     Object[] listeners = listenerList.getListenerList();
  783.     // Process the listeners last to first, notifying
  784.     // those that are interested in this event
  785.     for (int i = listeners.length-2; i>=0; i-=2) {
  786.         if (listeners[i]==ChangeListener.class) {
  787.         // Lazily create the event:
  788.         if (changeEvent == null)
  789.             changeEvent = new ChangeEvent(this);
  790.         ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  791.         }           
  792.     }
  793.     }    
  794.  
  795.     /**
  796.      * adds an ActionListener to the button
  797.      */
  798.     public void addActionListener(ActionListener l) {
  799.     listenerList.add(ActionListener.class, l);
  800.     }
  801.     
  802.     /**
  803.      * removes an ActionListener from the button
  804.      */
  805.     public void removeActionListener(ActionListener l) {
  806.     listenerList.remove(ActionListener.class, l);
  807.     }
  808.     
  809.     
  810.     /**
  811.      * Subclasses that want to handle ChangeEvents differently
  812.      * can override this to return another ChangeListener implementation.
  813.      */
  814.     protected ChangeListener createChangeListener() {
  815.     return (ChangeListener) new ButtonChangeListener();
  816.     }
  817.  
  818.     /**
  819.      * Extend ChangeListener to be serializable
  820.      * <p>
  821.      * Warning: serialized objects of this class will not be compatible with
  822.      * future swing releases.  The current serialization support is appropriate
  823.      * for short term storage or RMI between Swing1.0 applications.  It will
  824.      * not be possible to load serialized Swing1.0 objects with future releases
  825.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  826.      * baseline for the serialized form of Swing objects.
  827.      */
  828.     protected class ButtonChangeListener implements ChangeListener, Serializable {
  829.     ButtonChangeListener() {
  830.     }
  831.  
  832.     public void stateChanged(ChangeEvent e) {
  833.         fireStateChanged();
  834.         repaint();
  835.     }
  836.     }
  837.  
  838.  
  839.     /*
  840.      * Notify all listeners that have registered interest for
  841.      * notification on this event type.  The event instance 
  842.      * is lazily created using the parameters passed into 
  843.      * the fire method.
  844.      * @see EventListenerList
  845.      */
  846.     protected void fireActionPerformed(ActionEvent event) {
  847.     // Guaranteed to return a non-null array
  848.     Object[] listeners = listenerList.getListenerList();
  849.     ActionEvent e = null;
  850.     // Process the listeners last to first, notifying
  851.     // those that are interested in this event
  852.     for (int i = listeners.length-2; i>=0; i-=2) {
  853.         if (listeners[i]==ActionListener.class) {
  854.         // Lazily create the event:
  855.         if (e == null) {
  856.             e = new ActionEvent(AbstractButton.this,
  857.                     ActionEvent.ACTION_PERFORMED,
  858.                     getActionCommand());
  859.         }
  860.         ((ActionListener)listeners[i+1]).actionPerformed(e);
  861.         }           
  862.     }
  863.     }
  864.     
  865.     /*
  866.      * Notify all listeners that have registered interest for
  867.      * notification on this event type.  The event instance 
  868.      * is lazily created using the parameters passed into 
  869.      * the fire method.
  870.      * @see EventListenerList
  871.      */
  872.     protected void fireItemStateChanged(ItemEvent event) {
  873.     // Guaranteed to return a non-null array
  874.     Object[] listeners = listenerList.getListenerList();
  875.     ItemEvent e = null;
  876.     // Process the listeners last to first, notifying
  877.     // those that are interested in this event
  878.     for (int i = listeners.length-2; i>=0; i-=2) {
  879.         if (listeners[i]==ItemListener.class) {
  880.         // Lazily create the event:
  881.         if (e == null) {
  882.             e = new ItemEvent(AbstractButton.this,
  883.                                       ItemEvent.ITEM_STATE_CHANGED,
  884.                                       AbstractButton.this,
  885.                                       event.getStateChange());
  886.         }
  887.         ((ItemListener)listeners[i+1]).itemStateChanged(e);
  888.         }           
  889.     }
  890.     }
  891.     
  892.  
  893.     private class ForwardActionEvents implements ActionListener, Serializable {
  894.     public void actionPerformed(ActionEvent event) {
  895.         fireActionPerformed(event);
  896.     }
  897.     }
  898.  
  899.     protected ActionListener createActionListener() {
  900.     return new ForwardActionEvents();
  901.     }
  902.  
  903.  
  904.     private class ForwardItemEvents implements ItemListener, Serializable {
  905.     public void itemStateChanged(ItemEvent event) {
  906.         fireItemStateChanged(event);
  907.     }
  908.     }
  909.  
  910.     protected ItemListener createItemListener() {
  911.         return new ForwardItemEvents();
  912.     }
  913.  
  914.     
  915.     /**
  916.      * Enables (or disables) the button.
  917.      */
  918.     public void setEnabled(boolean b) {
  919.     super.setEnabled(b);
  920.     model.setEnabled(b);
  921.     }
  922.  
  923.     // *** Deprecated java.awt.Button APIs below *** //
  924.     
  925.     /**
  926.      * @deprecated - Replaced by getText()
  927.      */
  928.     public String getLabel() {
  929.     return getText();
  930.     }
  931.     
  932.     /**
  933.      * @deprecated - Replaced by setText(text)
  934.      * @beaninfo
  935.      *        bound: true
  936.      *  description: Replace by setText(text)
  937.      */
  938.     public void setLabel(String label) {
  939.     setText(label);
  940.     }
  941.  
  942.     /**
  943.      * adds an ItemListener to the checkbox
  944.      */
  945.     public void addItemListener(ItemListener l) {
  946.     listenerList.add(ItemListener.class, l);
  947.     }
  948.     
  949.     /**
  950.      * removes an ItemListener from the button
  951.      */
  952.     public void removeItemListener(ItemListener l) {
  953.     listenerList.remove(ItemListener.class, l);
  954.     }
  955.  
  956.     public Object[] getSelectedObjects() {
  957.     // REMINDER: finish
  958.     return null; 
  959.     }
  960.  
  961.     protected void init(String text, Icon icon) {
  962.     setLayout(new OverlayLayout(this));
  963.  
  964.     if(text != null) {
  965.         setText(text);
  966.     }
  967.     
  968.     if(icon != null) {
  969.         setIcon(icon);
  970.     }
  971.     
  972.     // Set the UI
  973.     updateUI();
  974.     
  975.     // Listen for Focus events
  976.     addFocusListener(
  977.         new FocusListener() {
  978.         public void focusGained(FocusEvent event) {
  979.         if (accessibleContext != null) {
  980.             accessibleContext.firePropertyChange(
  981.             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  982.             null, AccessibleState.FOCUSED);
  983.         }
  984.         }
  985.         public void focusLost(FocusEvent event) {
  986.         if (accessibleContext != null) {
  987.             accessibleContext.firePropertyChange(
  988.             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  989.             null, AccessibleState.FOCUSED);
  990.         }
  991.         // repaint focus is lost
  992.         if(isFocusPainted()) {
  993.             repaint();
  994.         }
  995.         }
  996.     }
  997.     );
  998.  
  999.     setAlignmentX(LEFT_ALIGNMENT);
  1000.     }
  1001.     
  1002.  
  1003. ///////////////////
  1004. // Accessibility support
  1005. ///////////////////
  1006.     /**
  1007.      * Accessiblity support.
  1008.      * <p>
  1009.      * Warning: serialized objects of this class will not be compatible with
  1010.      * future swing releases.  The current serialization support is appropriate
  1011.      * for short term storage or RMI between Swing1.0 applications.  It will
  1012.      * not be possible to load serialized Swing1.0 objects with future releases
  1013.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1014.      * baseline for the serialized form of Swing objects.
  1015.      */
  1016.     protected abstract class AccessibleAbstractButton
  1017.     extends AccessibleJComponent implements AccessibleValue {
  1018.  
  1019.         /**
  1020.          * Get the accessible name of this object.  
  1021.          *
  1022.          * @return the localized name of the object -- can be null if this 
  1023.          * object does not have a name
  1024.          */
  1025.         public String getAccessibleName() {
  1026.             if (accessibleName != null) {
  1027.                 return accessibleName;
  1028.             } else {
  1029.                 if (getText() == null) {
  1030.                 return super.getAccessibleName();
  1031.                 } else {
  1032.                 return getText();
  1033.                 }
  1034.             }
  1035.         }
  1036.  
  1037.         /**
  1038.          * Get the state set of this object.
  1039.          *
  1040.          * @return an instance of AccessibleState containing the current state 
  1041.          * of the object
  1042.          * @see AccessibleState
  1043.          */
  1044.         public AccessibleStateSet getAccessibleStateSet() {
  1045.         AccessibleStateSet states = super.getAccessibleStateSet();
  1046.             if (getModel().isArmed()) {
  1047.                 states.add(AccessibleState.ARMED);
  1048.             }
  1049.             if (hasFocus()) {
  1050.                 states.add(AccessibleState.FOCUSED);
  1051.             }
  1052.             if (getModel().isPressed()) {
  1053.                 states.add(AccessibleState.PRESSED);
  1054.             }
  1055.             if (isSelected()) {
  1056.                 states.add(AccessibleState.CHECKED);
  1057.             }
  1058.             return states;
  1059.         }
  1060.  
  1061.         /**
  1062.          * Get the AccessibleValue associated with this object if one
  1063.          * exists.  Otherwise return null.
  1064.          */
  1065.         public AccessibleValue getAccessibleValue() {
  1066.         return this;
  1067.         }
  1068.  
  1069.         /**
  1070.          * Returns the number of Actions available in this object.
  1071.          * If there is more than one, the first one is the "default"
  1072.          * action.
  1073.          *
  1074.          * @return the number of Actions in this object
  1075.          */
  1076.         public int getAccessibleActionCount() {
  1077.             return 1;
  1078.         }
  1079.     
  1080.         /**
  1081.          * Return a description of the specified action of the object.
  1082.          *
  1083.          * @param i zero-based index of the actions
  1084.          */
  1085.         public String getAccessibleActionDescription(int i) {
  1086.         if (i == 0) {
  1087.                 // [[[PENDING:  WDW -- need to provide a localized string]]]
  1088.                 return new String("click");
  1089.         } else {
  1090.         return null;
  1091.         }
  1092.         }
  1093.     
  1094.         /**
  1095.          * Perform the specified Action on the object
  1096.          *
  1097.          * @param i zero-based index of actions
  1098.          * @return true if the the action was performed; else false.
  1099.          */
  1100.         public boolean doAccessibleAction(int i) {
  1101.         if (i == 0) {
  1102.                 doClick();
  1103.                 return true;
  1104.         } else {
  1105.         return false;
  1106.         }
  1107.         }
  1108.  
  1109.         /**
  1110.          * Get the value of this object as a Number.
  1111.          *
  1112.          * @return An Integer of 0 if this isn't selected or an Integer of 1 if
  1113.          * this is selected.
  1114.          * @see #isSelected
  1115.          */
  1116.         public Number getCurrentAccessibleValue() {
  1117.             if (isSelected()) {
  1118.                 return new Integer(1);
  1119.             } else {
  1120.                 return new Integer(0);
  1121.             }
  1122.         }
  1123.  
  1124.         /**
  1125.          * Set the value of this object as a Number.
  1126.          *
  1127.          * @return True if the value was set.
  1128.          */
  1129.         public boolean setCurrentAccessibleValue(Number n) {
  1130.         if (n instanceof Integer) {
  1131.             int i = n.intValue();
  1132.             if (i == 0) {
  1133.                 setSelected(false);
  1134.             } else {
  1135.             setSelected(true);
  1136.             }
  1137.             return true;
  1138.         } else {
  1139.             return false;
  1140.         }
  1141.         }
  1142.  
  1143.         /**
  1144.          * Get the minimum value of this object as a Number.
  1145.          *
  1146.          * @return An Integer of 0.
  1147.          */
  1148.         public Number getMinimumAccessibleValue() {
  1149.             return new Integer(0);
  1150.         }
  1151.  
  1152.         /**
  1153.          * Get the maximum value of this object as a Number.
  1154.          *
  1155.          * @return An Integer of 1.
  1156.          */
  1157.         public Number getMaximumAccessibleValue() {
  1158.             return new Integer(1);
  1159.         }
  1160.     }
  1161. }
  1162.  
  1163.  
  1164.