home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1999 February / CDW0299.iso / Demos / Cafe / Source.bin / Spinner.java < prev    next >
Encoding:
Java Source  |  1998-03-18  |  33.8 KB  |  1,166 lines

  1. package symantec.itools.awt.util.spinner;
  2.  
  3.  
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.beans.PropertyChangeEvent;
  7. import java.beans.PropertyChangeListener;
  8. import java.beans.PropertyVetoException;
  9. import java.beans.VetoableChangeListener;
  10. import java.io.Serializable;
  11. import java.util.ResourceBundle;
  12. import symantec.itools.awt.Orientation;
  13. import symantec.itools.beans.*;
  14.  
  15.  
  16. //     01/29/97    TWB    Integrated changes from Macintosh
  17. //    01/30/97    RKM    Changed updateText to check if the text has changed, to avoid flicker
  18. //                    Also changed paint to first call updateText and removed ifdef MAC
  19. //    06/02/97    MSH Updated to Java 1.1
  20. //    06/03/97    LAB Polished update to Java 1.1.
  21. //                    Changed the package to symantec.itools.awt.util.spinner.
  22. //    07/18/97    LAB Added add/removeNotify to handle event listener registration.
  23. //                    Made sourceActionEvent protected instead of public.
  24. //  07/30/97    CAR Inner adaptor class implements java.io.Serializable
  25. //    09/02/97    RKM    Better code in updateText()
  26. //                    Added getEntryFieldText() as per request from newsgroup
  27. //  08/24/87    CAR hooked up actionlistener to textfield to listen for changes to the text
  28. //                  call updateText() from actionPerformed when textField's text changes
  29. //                  call invalidate/validate in setOrientation
  30. //  08/28/97    LAB    Made the spinner buttons disable and enable according to the value.  Implemented
  31. //                    getPreferredSize and getMinimumSize (Addresses Mac Bug #7518).  Changed the
  32. //                    property name strings in bound and constrained event messages to match the Bean
  33. //                    Spec naming conventions.
  34. //  09/11/97    LAB    Added listener registration code to setOrientation to remove and add our
  35. //                    listener to the newly created horizontal or vertical spin button panel.
  36. //                    Fixes a problem when you switched orientations and the spinner no longer
  37. //                    spun (Addresses Mac Bug#7822).
  38. //  10/05/97    LAB    Added mechanism for internally constrained properties to be validated
  39. //                    after the component is added to the form to avoid code-gen order specific
  40. //                    dependencies.
  41. //  10/06/97    LAB    Changed addNotify to call it's super after listeners are hooked up so
  42. //                    verifyContstrainedPropertyValues will be called after the listeners
  43. //                    are hooked up.  Changed order of calls in verifyContstrainedPropertyValues
  44. //                    method to reflect dependancy correctly.  Changed setMax, setMin, and
  45. //                    setCurrent to set the temp values to the current values when changing the
  46. //                    current values.  Changed getMax, getMin, and getCurrent to return the temp
  47. //                    values if the component is not added. This fixes a problem at design time
  48. //                    where the component would revert to it's default state after a back run.
  49. //  10/12/97    LAB    Changed doLayout so if the component is sized smaller than the preferred
  50. //                    size for the textfield and buttons, the textfield is shortened (Addresses
  51. //                    Mac Bug #9051).  When the textField fires an action event, the focus is
  52. //                    now requested by the Spinner (this takes the focus away from the textField).
  53. //                    Rearranged addNotify to correctly add the action listener to the textField
  54. //                    (Addresses Mac Bug #9200).
  55. //  02/05/98    DS  Re-write of GUI
  56.  
  57. /**
  58.  * This abstract class is used to create spinners. A spinner is a component
  59.  * with two small direction buttons that lets the user scroll a list of
  60.  * predetermined values to select one, or possibly enter a new legal value.
  61.  * @see symantec.itools.awt.util.spinner.ListSpinner
  62.  * @see symantec.itools.awt.util.spinner.NumericSpinner
  63.  * @version 1.1, June 2, 1997
  64.  * @author Symantec
  65.  */
  66. public abstract class Spinner
  67.     extends    Panel
  68.     implements Orientation,
  69.                Serializable
  70. {
  71.     class Action
  72.         implements ActionListener,
  73.                    java.io.Serializable
  74.     {
  75.         public void actionPerformed(ActionEvent e)
  76.         {
  77.             if(e.getSource() instanceof TextField)
  78.             {
  79.                    if(((TextField)e.getSource()) == textFld)
  80.                    {
  81.                      updateText(false);
  82.                     //Take the focus away from the edit box
  83.                     requestFocus();
  84.                        return;
  85.                 }
  86.             }
  87.  
  88.             String cmdStr = "";
  89.             String actionCommand = e.getActionCommand();
  90.  
  91.             if(actionCommand.equals("Increment"))
  92.             {
  93.                 scrollUp();
  94.                 cmdStr = "ScrollUp";
  95.                 sourceActionEvent(cmdStr);
  96.             }
  97.             else if(actionCommand.equals("Decrement"))
  98.             {
  99.                 scrollDown();
  100.                 cmdStr = "ScrollDown";
  101.                 sourceActionEvent(cmdStr);
  102.             }
  103.         }
  104.     }
  105.  
  106.     /**
  107.      * This is the PropertyChangeEvent handling inner class for the constrained Current property.
  108.      * Handles vetoing Current values that are not valid.
  109.      */
  110.     class CurrentVeto
  111.         implements VetoableChangeListener,
  112.                    java.io.Serializable
  113.     {
  114.         /**
  115.          * This method gets called when an attempt to change the constrained Current property is made.
  116.          * Ensures the given Current value is valid for this component.
  117.          *
  118.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  119.          *             event source and the property that has changed.
  120.          * @exception PropertyVetoException if the recipient wishes the property
  121.          *              change to be rolled back.
  122.          */
  123.         public void vetoableChange(PropertyChangeEvent e)
  124.             throws PropertyVetoException
  125.         {
  126.             int i = ((Integer)e.getNewValue()).intValue();
  127.  
  128.             if(!isValidCurrentValue(i))
  129.             {
  130.                 throw new PropertyVetoException(errors.getString("InvalidCurrentValue") + i, e);
  131.             }
  132.         }
  133.     }
  134.  
  135.     /**
  136.      * This is the PropertyChangeEvent handling inner class for the constrained Max property.
  137.      * Handles vetoing Max values that are not valid.
  138.      */
  139.     class MaxVeto
  140.         implements VetoableChangeListener,
  141.                    Serializable
  142.     {
  143.         /**
  144.          * This method gets called when an attempt to change the constrained Current property is made.
  145.          * Ensures the given Max value is valid for this component.
  146.          *
  147.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  148.          *             event source and the property that has changed.
  149.          * @exception PropertyVetoException if the recipient wishes the property
  150.          *              change to be rolled back.
  151.          */
  152.         public void vetoableChange(PropertyChangeEvent e)
  153.             throws PropertyVetoException
  154.         {
  155.             int i = ((Integer)e.getNewValue()).intValue();
  156.  
  157.             if(!isValidMaxValue(i))
  158.             {
  159.                 throw new PropertyVetoException(errors.getString("InvalidMaxValue") + i, e);
  160.             }
  161.         }
  162.     }
  163.  
  164.     /**
  165.      * This is the PropertyChangeEvent handling inner class for the constrained Min property.
  166.      * Handles vetoing Min values that are not valid.
  167.      */
  168.     class MinVeto
  169.         implements VetoableChangeListener,
  170.                    java.io.Serializable
  171.     {
  172.         /**
  173.          * This method gets called when an attempt to change the constrained Current property is made.
  174.          * Ensures the given Min value is valid for this component.
  175.          *
  176.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  177.          *             event source and the property that has changed.
  178.          * @exception PropertyVetoException if the recipient wishes the property
  179.          *              change to be rolled back.
  180.          */
  181.         public void vetoableChange(PropertyChangeEvent e)
  182.             throws PropertyVetoException
  183.         {
  184.             int i = ((Integer)e.getNewValue()).intValue();
  185.  
  186.             if(!isValidMinValue(i))
  187.             {
  188.                 throw new PropertyVetoException(errors.getString("InvalidMinValue") + i, e);
  189.             }
  190.         }
  191.     }
  192.  
  193.     /**
  194.      * The default spinner orientation.
  195.      */
  196.     protected static int ORIENTATION_DEFAULT = ORIENTATION_VERTICAL;
  197.  
  198.     /**
  199.      * Reserved.
  200.      */
  201.     protected String                text;
  202.     /**
  203.      * Reserved.
  204.      */
  205.     protected int                   textWidth;
  206.     /**
  207.      * Reserved.
  208.      * @see #getOrientation
  209.      * @see #setOrientation
  210.      */
  211.     protected int                   orientation;
  212.     /**
  213.      * Whether the value can wrap from max to min, and from min to max.
  214.      * @see #isWrappable
  215.      * @see #setWrappable
  216.      */
  217.     protected boolean               wrappable;
  218.     /**
  219.      * Whether the Spinner's TextField is editable.
  220.      * @see #isEditable
  221.      * @see #setEditable
  222.      */
  223.     protected boolean               editable;
  224.     /**
  225.      * The minimum value the spinner may have.
  226.      * @see #getMin
  227.      * @see #setMin
  228.      */
  229.     protected int                   min;
  230.     /**
  231.      * The maximum value the spinner may have.
  232.      * @see #getMax
  233.      * @see #setMax
  234.      */
  235.     protected int                   max;
  236.     /**
  237.      * The current spinner value.
  238.      * @see #getCurrent
  239.      * @see #setCurrent
  240.      */
  241.     protected int                   current;
  242.     /**
  243.      * The amount the spinner's value is changed when scrolling step is taken.
  244.      * @see #scrollUp
  245.      * @see #scrollDown
  246.      */
  247.     protected int                   increment;
  248.     /**
  249.      * Tracks listeners for all vetoable property change events.
  250.      * @see #addVetoableChangeListener
  251.      * @see #removeVetoableChangeListener
  252.      */
  253.     protected VetoableChangeSupport vetos;
  254.     /**
  255.      * Tracks listeners for all property change events.
  256.      * @see #addPropertyChangeListener
  257.      * @see #removePropertyChangeListener
  258.      */
  259.     protected PropertyChangeSupport changes;
  260.     /**
  261.      * Error reporting strings.
  262.      */
  263.     protected ResourceBundle        errors;
  264.       /**
  265.      * The action listener which will receive action events
  266.      * from this component.
  267.      * @see #addActionListener
  268.      * @see #removeActionListener
  269.      */
  270.     protected ActionListener        actionListener;
  271.     /**
  272.      * A PropertyChangeEvent listener that constrains the "current" property as needed.
  273.      * @see #current
  274.      * @see #maxVeto
  275.      * @see #minVeto
  276.      */
  277.     protected CurrentVeto            currentVeto;
  278.     /**
  279.      * A PropertyChangeEvent listener that constrains the "max" property as needed.
  280.      * @see #max
  281.      * @see #currentVeto
  282.      * @see #minVeto
  283.      */
  284.     protected MaxVeto                maxVeto;
  285.     /**
  286.      * A PropertyChangeEvent listener that constrains the "min" property as needed.
  287.      * @see #min
  288.      * @see #currentVeto
  289.      * @see #maxVeto
  290.      */
  291.     protected MinVeto                minVeto;
  292.     /**
  293.      * An ActionEvent listener that handles typical spinner actions.
  294.      */
  295.     protected Action                action;
  296.     /**
  297.      * Tracks whether this component has been added to a container.
  298.      */
  299.     protected boolean               added;
  300.  
  301.     {
  302.         min       = 0;
  303.         max       = 0;
  304.         increment = 1;
  305.         current   = 0;
  306.         textWidth = 0;
  307.         vetos     = new VetoableChangeSupport(this);
  308.         changes   = new PropertyChangeSupport(this);
  309.         added     = false;
  310.     }
  311.  
  312.     /**
  313.      * Constructs a default spinner. The current value is 0,
  314.      * the minimum value is 0, the maximum value is 1, the increment is 1,
  315.      * it is not wrappable, and has a vertical orientation.
  316.      */
  317.     public Spinner()
  318.     {
  319.         //{{INIT_CONTROLS
  320.         GridBagLayout gridBagLayout;
  321.         gridBagLayout = new GridBagLayout();
  322.         super.setLayout(gridBagLayout);
  323.         setSize(61,20);
  324.         textFld = new java.awt.TextField();
  325.         textFld.setBounds(0,0,100,20);
  326.         GridBagConstraints gbc;
  327.         gbc = new GridBagConstraints();
  328.         gbc.gridx = 0;
  329.         gbc.gridy = 0;
  330.         gbc.weightx = 1.0;
  331.         gbc.weighty = 1.0;
  332.         gbc.fill = GridBagConstraints.HORIZONTAL;
  333.         gbc.insets = new Insets(0,0,0,0);
  334.         ((GridBagLayout)getLayout()).setConstraints(textFld, gbc);
  335.         add(textFld);
  336.         buttons = new symantec.itools.awt.util.spinner.SpinButtonPanel();
  337.         buttons.setLayout(new GridLayout(2,1,0,0));
  338.         buttons.setBounds(100,0,3,20);
  339.         gbc = new GridBagConstraints();
  340.         gbc.gridx = 1;
  341.         gbc.gridy = 0;
  342.         gbc.weightx = 0.05;
  343.         gbc.weighty = 1.0;
  344.         gbc.fill = GridBagConstraints.BOTH;
  345.         gbc.insets = new Insets(0,0,0,0);
  346.         ((GridBagLayout)getLayout()).setConstraints(buttons, gbc);
  347.         add(buttons);
  348.         //}}
  349.  
  350.         try
  351.         {
  352.             setWrappable(false);
  353.             setOrientation(ORIENTATION_DEFAULT);
  354.         }
  355.         catch(PropertyVetoException e)
  356.         {
  357.         }
  358.     }
  359.  
  360.     //{{DECLARE_CONTROLS
  361.     java.awt.TextField textFld;
  362.     symantec.itools.awt.util.spinner.SpinButtonPanel buttons;
  363.     //}}
  364.  
  365.     /**
  366.      * Conditionally enables editing of the Spinner's TextField.
  367.      * @param f true = allow editing;
  368.      *          false = disallow editing
  369.      *
  370.      * @exception PropertyVetoException
  371.      * if the specified property value is unacceptable
  372.      */
  373.     public void setEditable(boolean f) throws PropertyVetoException
  374.     {
  375.         if(editable != f)
  376.         {
  377.             Boolean oldValue;
  378.             Boolean newValue;
  379.  
  380.             oldValue = new Boolean(editable);
  381.             newValue = new Boolean(f);
  382.             vetos.fireVetoableChange("editable", oldValue, newValue);
  383.             editable = f;
  384.             textFld.setEditable(editable);
  385.             changes.firePropertyChange("editable", oldValue, newValue);
  386.         }
  387.     }
  388.  
  389.     /**
  390.      * @deprecated
  391.      * @see #isEditable
  392.      */
  393.     public boolean getEditable()
  394.     {
  395.         return editable;
  396.     }
  397.  
  398.     /**
  399.      * Returns whether the Spinner's TextField is editable.
  400.      * @return  <code>true</code> if the TextField can be edited,
  401.      *          <code>false</code> otherwise
  402.      * @see #setEditable
  403.      */
  404.     public boolean isEditable()
  405.     {
  406.         return editable;
  407.     }
  408.  
  409.     /**
  410.      * Sets whether the spinner buttons are laid out one above the other or
  411.      * one beside the other.
  412.      * @param o the new orientation, one of: ORIENTATION_VERTICAL, or ORIENTATION_HORIZONTAL
  413.      * @exception PropertyVetoException
  414.      * if the specified property value is unacceptable
  415.      * @see #getOrientation
  416.      * @see symantec.itools.awt.Orientation#ORIENTATION_VERTICAL
  417.      * @see symantec.itools.awt.Orientation#ORIENTATION_HORIZONTAL
  418.     */
  419.     public void setOrientation(int o)
  420.         throws PropertyVetoException
  421.     {
  422.         if(orientation != o)
  423.         {
  424.             Integer oldValue;
  425.             Integer newValue;
  426.  
  427.             oldValue = new Integer(orientation);
  428.             newValue = new Integer(o);
  429.             vetos.fireVetoableChange("orientation", oldValue, newValue);
  430.             orientation = o;
  431.             buttons.setOrientation(orientation);
  432.             changes.firePropertyChange("orientation", oldValue, newValue);
  433.         }
  434.     }
  435.  
  436.     /**
  437.      * Gets whether the spinner buttons are laid out one above the other or
  438.      * one beside the other.
  439.      * @return the orientation, one of: ORIENTATION_VERTICAL, or ORIENTATION_HORIZONTAL
  440.      * @see #setOrientation
  441.      * @see symantec.itools.awt.Orientation#ORIENTATION_VERTICAL
  442.      * @see symantec.itools.awt.Orientation#ORIENTATION_HORIZONTAL
  443.     */
  444.     public int getOrientation()
  445.     {
  446.         return (orientation);
  447.     }
  448.  
  449.     /**
  450.      * Sets whether the value can wrap from max to min, and from min to max.
  451.      * @param f <code>true</code> to allow the value to wrap
  452.      * @see #isWrappable
  453.      * @exception PropertyVetoException
  454.      * if the specified property value is unacceptable
  455.      */
  456.     public void setWrappable(boolean f)
  457.         throws PropertyVetoException
  458.     {
  459.         if(wrappable != f)
  460.         {
  461.             Boolean oldValue;
  462.             Boolean newValue;
  463.  
  464.             oldValue = new Boolean(wrappable);
  465.             newValue = new Boolean(f);
  466.             vetos.fireVetoableChange("wrappable", oldValue, newValue);
  467.             wrappable = f;
  468.             updateButtonStatus();
  469.             changes.firePropertyChange("wrappable", oldValue, newValue);
  470.         }
  471.     }
  472.  
  473.     /**
  474.      * @deprecated
  475.      * @see #isWrappable
  476.      */
  477.     public boolean getWrappable()
  478.     {
  479.         return (wrappable);
  480.     }
  481.  
  482.     /**
  483.      * Gets whether the value can wrap from max to min, and from min to max.
  484.      * @return <code>true</code> if the value is allowed to wrap
  485.      * @see #setWrappable
  486.      */
  487.     public boolean isWrappable()
  488.     {
  489.         return (wrappable);
  490.     }
  491.  
  492.     public Dimension getPreferredSize()
  493.     {
  494.         Dimension   textFldDim;
  495.         Dimension   btnsDim;
  496.  
  497.         textFldDim  = textFld.getPreferredSize();
  498.         btnsDim     = buttons.getPreferredSize();
  499.  
  500.         return (new Dimension(textFldDim.width + btnsDim.width, Math.max(textFldDim.height, btnsDim.height)));
  501.     }
  502.  
  503.     public Dimension getMinimumSize()
  504.     {
  505.         return (getPreferredSize());
  506.     }
  507.  
  508.     /**
  509.      * Sets the minimum value the spinner may have.
  510.      * @param i the new minimum value
  511.      * @see #getMin
  512.      *
  513.      * @exception PropertyVetoException
  514.      * if the specified property value is unacceptable
  515.      */
  516.     public void setMin(int i)
  517.         throws PropertyVetoException
  518.     {
  519.         if(min != i)
  520.         {
  521.             Integer oldValue;
  522.             Integer newValue;
  523.  
  524.             oldValue = new Integer(min);
  525.             newValue = new Integer(i);
  526.             vetos.fireVetoableChange("min", oldValue, newValue);
  527.             min = i;
  528.  
  529.             if(getCurrent() < min)
  530.             {
  531.                    setCurrent(min);
  532.             }
  533.             else
  534.             {
  535.                 updateButtonStatus();
  536.             }
  537.  
  538.             changes.firePropertyChange("min", oldValue, newValue);
  539.         }
  540.     }
  541.  
  542.     /**
  543.      * Gets the current minimum value the spinner may have.
  544.      * @return the current minimum value
  545.      * @see #setMin
  546.      */
  547.     public int getMin()
  548.     {
  549.         return (min);
  550.     }
  551.  
  552.     /**
  553.      * Sets the maximum value the spinner may have.
  554.      * @param i the new maximum value
  555.      * @see #getMax
  556.      *
  557.      * @exception PropertyVetoException
  558.      * if the specified property value is unacceptable
  559.      */
  560.     public void setMax(int i) throws PropertyVetoException
  561.     {
  562.         if(max != i)
  563.         {
  564.             Integer oldValue;
  565.             Integer newValue;
  566.  
  567.             oldValue = new Integer(max);
  568.             newValue = new Integer(i);
  569.             vetos.fireVetoableChange("max", oldValue, newValue);
  570.             max = i;
  571.  
  572.             if(getCurrent() > max)
  573.             {
  574.                 setCurrent(max);
  575.             }
  576.             else
  577.             {
  578.                 updateButtonStatus();
  579.             }
  580.  
  581.             changes.firePropertyChange("max", oldValue, newValue);
  582.         }
  583.     }
  584.  
  585.     /**
  586.      * Gets the current maximum value the spinner may have.
  587.      * @return the current maximum value
  588.      * @see #setMax
  589.      */
  590.     public int getMax()
  591.     {
  592.         return (max);
  593.     }
  594.  
  595.     /**
  596.      * Sets the value of the spinner.
  597.      * @param i the new value
  598.      * @see #getCurrent
  599.      *
  600.      * @exception PropertyVetoException
  601.      * if the specified property value is unacceptable
  602.      */
  603.     public void setCurrent(int i) throws PropertyVetoException
  604.     {
  605.         if(current != i)
  606.         {
  607.                Integer oldValue;
  608.             Integer newValue;
  609.  
  610.                oldValue = new Integer(current);
  611.             newValue = new Integer(i);
  612.             vetos.fireVetoableChange("current", oldValue, newValue);
  613.             current = i;
  614.             updateText(false);
  615.             updateButtonStatus();
  616.             changes.firePropertyChange("current", oldValue, newValue);
  617.         }
  618.     }
  619.  
  620.     /**
  621.      * Gets the current value of the spinner.
  622.      * @return the current spinner value
  623.      * @see #setCurrent
  624.      */
  625.     public int getCurrent()
  626.     {
  627.         return (current);
  628.     }
  629.  
  630.     /**
  631.      * Sets whether the spinner buttons will continually post notify events
  632.      * while pressed.
  633.      * @param f true = send messages; false = do not send messages
  634.      * @see #isNotifyWhilePressed
  635.      * @see #setDelay
  636.      * @see #getDelay
  637.      *
  638.      * @exception PropertyVetoException
  639.      * if the specified property value is unacceptable
  640.      */
  641.     public void setNotifyWhilePressed(boolean f)
  642.         throws PropertyVetoException
  643.     {
  644.         if(f != buttons.getNotifyWhilePressed())
  645.         {
  646.             Boolean oldValue;
  647.             Boolean newValue;
  648.  
  649.             oldValue = new Boolean(getNotifyWhilePressed());
  650.             newValue = new Boolean(f);
  651.             vetos.fireVetoableChange("notifyWhilePressed", oldValue, newValue);
  652.             buttons.setNotifyWhilePressed(f);
  653.             changes.firePropertyChange("notifyWhilePressed", oldValue, newValue);
  654.         }
  655.     }
  656.  
  657.     /**
  658.      * Gets the current notifyWhilePressed status.
  659.      * @return true if notify events posted while pressed, false otherwise
  660.      * @see #setNotifyWhilePressed
  661.      * @see #setDelay
  662.      * @see #getDelay
  663.      */
  664.     public boolean isNotifyWhilePressed()
  665.     {
  666.         return (buttons.isNotifyWhilePressed());
  667.     }
  668.  
  669.     /**
  670.      * @deprecated
  671.      * @see #isNotifyWhilePressed
  672.      */
  673.     public boolean getNotifyWhilePressed()
  674.     {
  675.         return isNotifyWhilePressed();
  676.     }
  677.  
  678.     /**
  679.      * Sets the notification event delay of the spinner buttons in milliseconds.
  680.      * @param d the delay between notification events in milliseconds
  681.      * @see #setNotifyWhilePressed
  682.      * @see #getDelay
  683.      *
  684.      * @exception PropertyVetoException
  685.      * if the specified property value is unacceptable
  686.      */
  687.     public void setDelay(int d) throws PropertyVetoException
  688.     {
  689.         if(d != buttons.getDelay())
  690.         {
  691.             Integer oldValue;
  692.             Integer newValue;
  693.  
  694.             oldValue = new Integer(buttons.getDelay());
  695.             newValue = new Integer(d);
  696.  
  697.             vetos.fireVetoableChange("delay", oldValue, newValue);
  698.             buttons.setDelay(d);
  699.             changes.firePropertyChange("delay", oldValue, newValue);
  700.         }
  701.     }
  702.  
  703.     /**
  704.      * Returns the current delay between notification events of the spinner
  705.      * buttons in milliseconds.
  706.      * @see #setNotifyWhilePressed
  707.      * @see #setDelay
  708.      */
  709.     public int getDelay()
  710.     {
  711.         return buttons.getDelay();
  712.     }
  713.  
  714.     /**
  715.      * Returns the text that is in the entry TextField.
  716.      */
  717.     public String getEntryFieldText()
  718.     {
  719.         return (textFld.getText());
  720.     }
  721.  
  722.     /**
  723.      * Takes no action.
  724.      * This is a standard Java AWT method which gets called to specify
  725.      * which layout manager should be used to layout the components in
  726.      * standard containers.
  727.      *
  728.      * Since layout managers CANNOT BE USED with this container the standard
  729.      * setLayout has been OVERRIDDEN for this container and does nothing.
  730.      *
  731.      * @param lm the layout manager to use to layout this container's components
  732.      * (IGNORED)
  733.      * @see java.awt.Container#getLayout
  734.      **/
  735.     public void setLayout(LayoutManager lm)
  736.     {
  737.     }
  738.  
  739.     /**
  740.      * Tells this component that it has been added to a container.
  741.      * This is a standard Java AWT method which gets called by the AWT when
  742.      * this component is added to a container. Typically, it is used to
  743.      * create this component's peer.
  744.      *
  745.      * It has been overridden here to hook-up event listeners.
  746.      * It is also used to setup the component, creating the TextField as needed.
  747.      *
  748.      * @see #removeNotify
  749.      */
  750.     public synchronized void addNotify()
  751.     {
  752.         super.addNotify();
  753.         added = true;
  754.         errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  755.  
  756.         //Hook up listeners
  757.         if(action == null)
  758.         {
  759.             action = new Action();
  760.             buttons.addActionListener(action);
  761.             textFld.addActionListener(action);
  762.         }
  763.  
  764.         if(currentVeto == null)
  765.         {
  766.             currentVeto = new CurrentVeto();
  767.             addCurrentListener(currentVeto);
  768.         }
  769.  
  770.         if(maxVeto == null)
  771.         {
  772.             maxVeto = new MaxVeto();
  773.             addMaxListener(maxVeto);
  774.         }
  775.  
  776.         if(minVeto == null)
  777.         {
  778.             minVeto = new MinVeto();
  779.             addMinListener(minVeto);
  780.         }
  781.  
  782.         updateText(true);
  783.     }
  784.  
  785.     /**
  786.      * Tells this component that it is being removed from a container.
  787.      * This is a standard Java AWT method which gets called by the AWT when
  788.      * this component is removed from a container. Typically, it is used to
  789.      * destroy the peers of this component and all its subcomponents.
  790.      *
  791.      * It has been overridden here to unhook event listeners.
  792.      *
  793.      * @see #addNotify
  794.      */
  795.     public synchronized void removeNotify()
  796.     {
  797.         //Unhook listeners
  798.         if(action != null)
  799.         {
  800.             textFld.removeActionListener(action);
  801.             buttons.removeActionListener(action);
  802.             action = null;
  803.         }
  804.  
  805.         if(currentVeto != null)
  806.         {
  807.             removeCurrentListener(currentVeto);
  808.             currentVeto = null;
  809.         }
  810.  
  811.         if(maxVeto != null)
  812.         {
  813.             removeMaxListener(maxVeto);
  814.             maxVeto = null;
  815.         }
  816.  
  817.         if(minVeto != null)
  818.         {
  819.             removeMinListener(minVeto);
  820.             minVeto = null;
  821.         }
  822.  
  823.         super.removeNotify();
  824.     }
  825.  
  826.       /**
  827.      * Adds the specified action listener to receive action events
  828.      * from this component.
  829.      * @param l the action listener
  830.      * @see #removeActionListener
  831.      */
  832.     public synchronized void addActionListener(ActionListener l)
  833.     {
  834.         actionListener = AWTEventMulticaster.add(actionListener, l);
  835.     }
  836.  
  837.     /**
  838.      * Removes the specified action listener so it no longer receives
  839.      * action events from this component.
  840.      * @param l the action listener
  841.      * @see #addActionListener
  842.      */
  843.     public synchronized void removeActionListener(ActionListener l)
  844.     {
  845.         actionListener = AWTEventMulticaster.remove(actionListener, l);
  846.     }
  847.  
  848.     /**
  849.      * Adds a listener for all property change events.
  850.      * @param listener the listener to add
  851.      * @see #removePropertyChangeListener
  852.      */
  853.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  854.     {
  855.         changes.addPropertyChangeListener(listener);
  856.     }
  857.  
  858.     /**
  859.      * Removes a listener for all property change events.
  860.      * @param listener the listener to remove
  861.      * @see #addPropertyChangeListener
  862.      */
  863.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  864.     {
  865.         changes.removePropertyChangeListener(listener);
  866.     }
  867.  
  868.     /**
  869.      * Adds a listener for all vetoable property change events.
  870.      * @param listener the listener to add
  871.      * @see #removeVetoableChangeListener
  872.      */
  873.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  874.     {
  875.         vetos.addVetoableChangeListener(listener);
  876.     }
  877.  
  878.     /**
  879.      * Removes a listener for all vetoable property change events.
  880.      * @param listener the listener to remove
  881.      * @see #addVetoableChangeListener
  882.      */
  883.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  884.     {
  885.         vetos.removeVetoableChangeListener(listener);
  886.     }
  887.  
  888.     /**
  889.      * Adds a listener for the current property changes.
  890.      * @param listener the listener to add.
  891.      * @see #removeCurrentListener(java.beans.PropertyChangeListener)
  892.      */
  893.     public synchronized void addCurrentListener(PropertyChangeListener listener)
  894.     {
  895.         changes.addPropertyChangeListener("current", listener);
  896.     }
  897.  
  898.     /**
  899.      * Removes a listener for the current property changes.
  900.      * @param listener the listener to remove.
  901.      * @see #addCurrentListener(java.beans.PropertyChangeListener)
  902.      */
  903.     public synchronized void removeCurrentListener(PropertyChangeListener listener)
  904.     {
  905.         changes.removePropertyChangeListener("current", listener);
  906.     }
  907.  
  908.     /**
  909.      * Adds a vetoable listener for the current property changes.
  910.      * @param listener the listener to add.
  911.      * @see #removeCurrentListener(java.beans.VetoableChangeListener)
  912.      */
  913.     public synchronized void addCurrentListener(VetoableChangeListener listener)
  914.     {
  915.         vetos.addVetoableChangeListener("current", listener);
  916.     }
  917.  
  918.     /**
  919.      * Removes a vetoable listener for the current property changes.
  920.      * @param listener the listener to remove.
  921.      * @see #addCurrentListener(java.beans.VetoableChangeListener)
  922.      */
  923.     public synchronized void removeCurrentListener(VetoableChangeListener listener)
  924.     {
  925.         vetos.removeVetoableChangeListener("current", listener);
  926.     }
  927.  
  928.     /**
  929.      * Adds a listener for the max property changes.
  930.      * @param listener the listener to add.
  931.      * @see #removeMaxListener(java.beans.PropertyChangeListener)
  932.      */
  933.     public synchronized void addMaxListener(PropertyChangeListener listener)
  934.     {
  935.         changes.addPropertyChangeListener("max", listener);
  936.     }
  937.  
  938.     /**
  939.      * Removes a listener for the max property changes.
  940.      * @param listener the listener to remove.
  941.      * @see #addMaxListener(java.beans.PropertyChangeListener)
  942.      */
  943.     public synchronized void removeMaxListener(PropertyChangeListener listener)
  944.     {
  945.         changes.removePropertyChangeListener("max", listener);
  946.     }
  947.  
  948.     /**
  949.      * Adds a vetoable listener for the max property changes.
  950.      * @param listener the listener to add.
  951.      * @see #removeMaxListener(java.beans.VetoableChangeListener)
  952.      */
  953.     public synchronized void addMaxListener(VetoableChangeListener listener)
  954.     {
  955.         vetos.addVetoableChangeListener("max", listener);
  956.     }
  957.  
  958.     /**
  959.      * Removes a vetoable listener for the max property changes.
  960.      * @param listener the listener to remove.
  961.      * @see #addMaxListener(java.beans.VetoableChangeListener)
  962.      */
  963.     public synchronized void removeMaxListener(VetoableChangeListener listener)
  964.     {
  965.         vetos.removeVetoableChangeListener("max", listener);
  966.     }
  967.  
  968.     /**
  969.      * Adds a listener for the min property changes.
  970.      * @param listener the listener to add.
  971.      * @see #removeMinListener(java.beans.PropertyChangeListener)
  972.      */
  973.     public synchronized void addMinListener(PropertyChangeListener listener)
  974.     {
  975.         changes.addPropertyChangeListener("min", listener);
  976.     }
  977.  
  978.     /**
  979.      * Removes a listener for the min property changes.
  980.      * @param listener the listener to remove.
  981.      * @see #addMinListener(java.beans.PropertyChangeListener)
  982.      */
  983.     public synchronized void removeMinListener(PropertyChangeListener listener)
  984.     {
  985.         changes.removePropertyChangeListener("min", listener);
  986.     }
  987.  
  988.     /**
  989.      * Adds a vetoable listener for the min property changes.
  990.      * @param listener the listener to add.
  991.      * @see #removeMinListener(java.beans.VetoableChangeListener)
  992.      */
  993.     public synchronized void addMinListener(VetoableChangeListener listener)
  994.     {
  995.         vetos.addVetoableChangeListener("min", listener);
  996.     }
  997.  
  998.     /**
  999.      * Removes a vetoable listener for the min property changes.
  1000.      * @param listener the listener to remove.
  1001.      * @see #addMinListener(java.beans.VetoableChangeListener)
  1002.      */
  1003.     public synchronized void removeMinListener(VetoableChangeListener listener)
  1004.     {
  1005.         vetos.removeVetoableChangeListener("min", listener);
  1006.     }
  1007.  
  1008.     /**
  1009.      * Is the given value valid for the Current property .
  1010.      * @param i the given value
  1011.      * @return true if the given value is acceptable, false if not.
  1012.      */
  1013.     protected boolean isValidCurrentValue(int i)
  1014.     {
  1015.         if (i > max || i < min)
  1016.             return false;
  1017.         else
  1018.             return true;
  1019.     }
  1020.  
  1021.     /**
  1022.      * Is the given value valid for the Max property .
  1023.      * @param i the given value
  1024.      * @return true if the given value is acceptable, false if not.
  1025.      */
  1026.     protected boolean isValidMaxValue(int i)
  1027.     {
  1028.         return (i >= min);
  1029.     }
  1030.  
  1031.     /**
  1032.      * Is the given value valid for the Min property .
  1033.      * @param i the given value
  1034.      * @return true if the given value is acceptable, false if not.
  1035.      */
  1036.     protected boolean isValidMinValue(int i)
  1037.     {
  1038.         return (i <= max);
  1039.     }
  1040.  
  1041.     /**
  1042.     * Fire an action event to the listeners
  1043.     */
  1044.     protected void sourceActionEvent( String s)
  1045.     {
  1046.         if (actionListener != null)
  1047.             actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, s));
  1048.     }
  1049.  
  1050.     /**
  1051.      * Increments the spinner's value and handles wrapping as needed.
  1052.      * @see #scrollDown
  1053.      * @see #increment
  1054.      */
  1055.     protected void scrollUp()
  1056.     {
  1057.         try
  1058.         {
  1059.             setCurrent(current + increment);
  1060.         }
  1061.         catch (PropertyVetoException exc)
  1062.         {
  1063.             if(wrappable)
  1064.             {
  1065.                 try { setCurrent(min); } catch (PropertyVetoException ex) {}
  1066.             }
  1067.             else
  1068.             {
  1069.                 try { setCurrent(max); } catch (PropertyVetoException ex) {}
  1070.             }
  1071.         }
  1072.  
  1073.         updateText(false);
  1074.     }
  1075.  
  1076.     /**
  1077.      * Decrements the spinner's value and handles wrapping as needed.
  1078.      * @see #scrollUp
  1079.      * @see #increment
  1080.      */
  1081.     protected void scrollDown()
  1082.     {
  1083.         try
  1084.         {
  1085.             setCurrent(current - increment);
  1086.         }
  1087.         catch (PropertyVetoException exc)
  1088.         {
  1089.             if (wrappable)
  1090.             {
  1091.                 try { setCurrent(max); } catch (PropertyVetoException exc1) {}
  1092.             }
  1093.             else
  1094.             {
  1095.                 try { setCurrent(min); } catch (PropertyVetoException exc1) {}
  1096.             }
  1097.         }
  1098.  
  1099.         updateText(false);
  1100.     }
  1101.  
  1102.     /**
  1103.      * Updates the text field with the current text, as needed or depending on the force flag.
  1104.      * @param force If true, causes the text field to update even if the value has not changed.
  1105.      * @see #getCurrentText
  1106.      */
  1107.     protected void updateText(boolean force)
  1108.     {
  1109.         String currentText;
  1110.  
  1111.         currentText = getCurrentText();
  1112.  
  1113.         //If the text has changed, put the new text into the text field
  1114.         if(force || !textFld.getText().equals(currentText))
  1115.         {
  1116.               textFld.setText(currentText);
  1117.         }
  1118.     }
  1119.  
  1120.     /**
  1121.      * Handles enabling or disabling the spinner buttons as needed.
  1122.      */
  1123.     protected void updateButtonStatus()
  1124.     {
  1125.         if(buttons != null)
  1126.         {
  1127.             if(wrappable)
  1128.             {
  1129.                 buttons.setUpButtonEnabled(true);
  1130.                 buttons.setDownButtonEnabled(true);
  1131.             }
  1132.             else
  1133.             {
  1134.                 if(current == max && current == min)
  1135.                 {
  1136.                     buttons.setUpButtonEnabled(false);
  1137.                     buttons.setDownButtonEnabled(false);
  1138.                 }
  1139.                 else if(current == max)
  1140.                 {
  1141.                     buttons.setUpButtonEnabled(false);
  1142.                     buttons.setDownButtonEnabled(true);
  1143.                 }
  1144.                 else if(current == min)
  1145.                 {
  1146.                     buttons.setUpButtonEnabled(true);
  1147.                     buttons.setDownButtonEnabled(false);
  1148.                 }
  1149.                 else
  1150.                 {
  1151.                     buttons.setUpButtonEnabled(true);
  1152.                     buttons.setDownButtonEnabled(true);
  1153.                 }
  1154.             }
  1155.         }
  1156.     }
  1157.  
  1158.     /**
  1159.      * Gets the currently selected string from the list.
  1160.      * @return the string currently visible in the Spinner
  1161.      * @see #updateText(boolean)
  1162.      */
  1163.     protected abstract String getCurrentText();
  1164. }
  1165.  
  1166.