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

  1. package symantec.itools.awt;
  2.  
  3. import java.awt.Panel;
  4. import java.awt.Checkbox;
  5. import java.awt.CheckboxGroup;
  6. import java.awt.Component;
  7. import java.awt.AWTEventMulticaster;
  8. import java.awt.event.ItemEvent;
  9. import java.awt.event.ItemListener;
  10. import java.util.Vector;
  11. import java.beans.PropertyVetoException;
  12. import java.beans.PropertyChangeListener;
  13. import java.beans.VetoableChangeListener;
  14. import java.beans.PropertyChangeEvent;
  15. import java.util.ResourceBundle;
  16.  
  17. //    01/27/97    RKM    Changed moveIntoGroup to preserve checkbox's state
  18. //    01/29/97    TWB    Integrated changes from Windows and RKM's changes
  19. //     01/29/97    TWB    Integrated changes from Macintosh
  20. //    06/01/97    RKM    Updated to support Java 1.1
  21. //                    Updated mechanism to keep track of contents of panel
  22. //    09/10/97    LAB    Made it extend BorderPanel to give it BorderPanel's properties (Addresses Mac
  23. //                    Bug #3086).  Made it fire an ItemEvent when the "station" changes (Addresses
  24. //                    Mac Bug #3093).
  25. //    10/05/97    LAB    Added mechanism for values passed to setSelectedRadioButtonIndex to be
  26. //                    validated on each call to addImpl to avoid code-gen order specific
  27. //                    dependencies.
  28.  
  29. /**
  30.  * Creates an rectangular panel area that automatically groups
  31.  * the RadioButtons that it contains.
  32.  * <p>
  33.  * All the RadioButtons within the RadioButtonGroupPanel act together. Only
  34.  * one of the RadioButtons can be "on" at a time.
  35.  * <p>
  36.  * @version 1.1, August 22, 1997
  37.  * @author Symantec
  38.  */
  39. public class RadioButtonGroupPanel extends BorderPanel implements java.awt.ItemSelectable
  40. {
  41.     /**
  42.      * Constructs a RadioButtonGroupPanel.
  43.      */
  44.     public RadioButtonGroupPanel()
  45.     {
  46.         group = new CheckboxGroup();
  47.         try
  48.         {
  49.             setPaddingTop(0);
  50.             setPaddingBottom(0);
  51.             setPaddingLeft(0);
  52.             setPaddingRight(0);
  53.         }
  54.         catch (PropertyVetoException exc) {}
  55.  
  56.         rbList = new Vector();
  57.         item = new IL();
  58.         tempSelectionIndex = -1;
  59.     }
  60.  
  61.     /**
  62.      * Returns the selected items or null if no items are selected.
  63.      */
  64.     public Object[] getSelectedObjects()
  65.     {
  66.         Object object[] = {getSelectedRadioButton()};
  67.         return object;
  68.     }
  69.  
  70.     /**
  71.      * Sets the current choice to the specified RadioButton.
  72.      * @param rb the current RadioButton (CheckBox) choice
  73.      */
  74.     public synchronized void setSelectedRadioButton(Checkbox rb) throws PropertyVetoException
  75.     {
  76.         Checkbox oldValue = getSelectedRadioButton();
  77.         if(! symantec.itools.util.GeneralUtils.objectsEqual(rb, oldValue))
  78.         {
  79.             vetos.fireVetoableChange("selectedRadioButton", oldValue, rb);
  80.  
  81.             group.setSelectedCheckbox(rb);
  82.             //Fire an event to our listeners, since the previous line doensn't seem to result in an event being fired.
  83.             sourceItemEvent(rb);
  84.  
  85.             changes.firePropertyChange("selectedRadioButton", oldValue, getSelectedRadioButton());
  86.         }
  87.     }
  88.  
  89.     /**
  90.      * Gets the current choice.
  91.      */
  92.     public Checkbox getSelectedRadioButton()
  93.     {
  94.         return group.getSelectedCheckbox();
  95.     }
  96.  
  97.     /**
  98.      * Sets the current choice to the specified RadioButton.
  99.      * @param index the index of the RadioButton to be the selected.
  100.      * @see #getSelectedRadioButtonIndex
  101.      */
  102.     public synchronized void setSelectedRadioButtonIndex(int index) throws PropertyVetoException
  103.     {
  104.         tempSelectionIndex = index;
  105.         if(isAdded)
  106.         {
  107.             Integer oldValue = new Integer(getSelectedRadioButtonIndex());
  108.             if(oldValue.intValue() != index)
  109.             {
  110.                 Integer newValue = new Integer(index);
  111.                 vetos.fireVetoableChange("selectedRadioButtonIndex", oldValue, newValue);
  112.  
  113.                 setSelectedRadioButton((Checkbox)rbList.elementAt(index));
  114.  
  115.                 changes.firePropertyChange("selectedRadioButtonIndex", oldValue, newValue);
  116.             }
  117.         }
  118.     }
  119.  
  120.     /**
  121.      * Gets the index of the current choice.
  122.      * @return the index of the selected RadioButton.  -1 if no selection.
  123.      * @see #setSelectedRadioButtonIndex
  124.      */
  125.     public int getSelectedRadioButtonIndex()
  126.     {
  127.         Checkbox cb = getSelectedRadioButton();
  128.         if(cb != null && rbList.contains(cb))
  129.         {
  130.             for(int i = 0; i < rbList.size(); i++)
  131.             {
  132.                 if((Checkbox)rbList.elementAt(i) == cb)
  133.                     return i;
  134.             }
  135.         }
  136.         return -1;
  137.     }
  138.  
  139.     /**
  140.      * Returns the String representation of this RadioButtonGroup's values.
  141.      * Convert to String.
  142.      */
  143.     public String toString()
  144.     {
  145.         return getClass().getName() + "[selectedRadioButton=" + getSelectedRadioButton() + "]";
  146.     }
  147.  
  148.     /**
  149.      * Removes the component at the specified index from this container.
  150.      * @param index the index of the component to be removed
  151.      * @see #add
  152.      */
  153.     public void remove(int index)
  154.     {
  155.         Component comp = getComponent(index);
  156.  
  157.         if(comp instanceof Checkbox)
  158.         {
  159.             ((Checkbox)comp).removeItemListener(item);
  160.             //Remove it from out internal list.
  161.             rbList.removeElement(comp);
  162.         }
  163.  
  164.         super.remove(index);
  165.     }
  166.  
  167.     /**
  168.      * Removes all the components from this container.
  169.      * @see #add
  170.      * @see #remove
  171.      */
  172.     public void removeAll()
  173.     {
  174.         Component[] comp = getComponents();
  175.  
  176.         for (int i = 0; i < comp.length; ++i)
  177.         {
  178.             if(comp[i] instanceof Checkbox)
  179.                 ((Checkbox)comp[i]).removeItemListener(item);
  180.         }
  181.  
  182.         //Reset our internal list.
  183.         rbList = new Vector();
  184.  
  185.         super.removeAll();
  186.     }
  187.  
  188.     /**
  189.      * Tells this component that it has been added to a container.
  190.      * This is a standard Java AWT method which gets called by the AWT when
  191.      * this component is added to a container. Typically, it is used to
  192.      * create this component's peer.
  193.      *
  194.      * It has been overridden here to hook-up event listeners.
  195.      *
  196.      * @see #removeNotify
  197.      */
  198.     public synchronized void addNotify()
  199.     {
  200.         super.addNotify();
  201.         
  202.         try
  203.         {
  204.             errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  205.         }
  206.         catch(Throwable ex)
  207.         {
  208.             errors = new symantec.itools.resources.ErrorsBundle();
  209.         }
  210.  
  211.         //Hook up listeners
  212.         if (indexVeto == null)
  213.         {
  214.             indexVeto = new IV();
  215.             addSelectedRadioButtonIndexListener(indexVeto);
  216.         }
  217.         isAdded = true;
  218.     }
  219.  
  220.     /**
  221.      * Tells this component that it is being removed from a container.
  222.      * This is a standard Java AWT method which gets called by the AWT when
  223.      * this component is removed from a container. Typically, it is used to
  224.      * destroy the peers of this component and all its subcomponents.
  225.      *
  226.      * It has been overridden here to unhook event listeners.
  227.      *
  228.      * @see #addNotify
  229.      */
  230.     public synchronized void removeNotify()
  231.     {
  232.         //Unhook listeners
  233.         if (indexVeto != null)
  234.         {
  235.             removeSelectedRadioButtonIndexListener(indexVeto);
  236.             indexVeto = null;
  237.         }
  238.  
  239.         super.removeNotify();
  240.     }
  241.  
  242.     /**
  243.      * Adds a listener for all event changes.
  244.      * @param listener the listener to add.
  245.      * @see #removePropertyChangeListener
  246.      */
  247.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  248.     {
  249.         super.addPropertyChangeListener(listener);
  250.         changes.addPropertyChangeListener(listener);
  251.     }
  252.  
  253.     /**
  254.      * Removes a listener for all event changes.
  255.      * @param listener the listener to remove.
  256.      * @see #addPropertyChangeListener
  257.      */
  258.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  259.     {
  260.         super.removePropertyChangeListener(listener);
  261.         changes.removePropertyChangeListener(listener);
  262.     }
  263.  
  264.     /**
  265.      * Adds a vetoable listener for all event changes.
  266.      * @param listener the listener to add.
  267.      * @see #removeVetoableChangeListener
  268.      */
  269.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  270.     {
  271.         super.addVetoableChangeListener(listener);
  272.         vetos.addVetoableChangeListener(listener);
  273.     }
  274.  
  275.     /**
  276.      * Removes a vetoable listener for all event changes.
  277.      * @param listener the listener to remove.
  278.      * @see #addVetoableChangeListener
  279.      */
  280.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  281.     {
  282.         super.removeVetoableChangeListener(listener);
  283.         vetos.removeVetoableChangeListener(listener);
  284.     }
  285.  
  286.     /**
  287.      * Adds a listener for the SelectedRadioButtonIndex property changes.
  288.      * @param listener the listener to add.
  289.      * @see #removeSelectedRadioButtonIndexListener(java.beans.PropertyChangeListener)
  290.      */
  291.     public synchronized void addSelectedRadioButtonIndexListener(PropertyChangeListener listener)
  292.     {
  293.         changes.addPropertyChangeListener("selectedRadioButtonIndex", listener);
  294.     }
  295.  
  296.     /**
  297.      * Removes a listener for the SelectedRadioButtonIndex property changes.
  298.      * @param listener the listener to remove.
  299.      * @see #addSelectedRadioButtonIndexListener(java.beans.PropertyChangeListener)
  300.      */
  301.     public synchronized void removeSelectedRadioButtonIndexListener(PropertyChangeListener listener)
  302.     {
  303.         changes.removePropertyChangeListener("selectedRadioButtonIndex", listener);
  304.     }
  305.  
  306.     /**
  307.      * Adds a vetoable listener for the SelectedRadioButtonIndex property changes.
  308.      * @param listener the listener to add.
  309.      * @see #removeSelectedRadioButtonIndexListener(java.beans.VetoableChangeListener)
  310.      */
  311.     public synchronized void addSelectedRadioButtonIndexListener(VetoableChangeListener listener)
  312.     {
  313.         vetos.addVetoableChangeListener("selectedRadioButtonIndex", listener);
  314.     }
  315.  
  316.     /**
  317.      * Removes a vetoable listener for the SelectedRadioButtonIndex property changes.
  318.      * @param listener the listener to remove.
  319.      * @see #addSelectedRadioButtonIndexListener(java.beans.VetoableChangeListener)
  320.      */
  321.     public synchronized void removeSelectedRadioButtonIndexListener(VetoableChangeListener listener)
  322.     {
  323.         vetos.removeVetoableChangeListener("selectedRadioButtonIndex", listener);
  324.     }
  325.  
  326.     /**
  327.      * Adds the specified item listener to receive item events
  328.      * from this component.
  329.      * @param l the item listener
  330.      * @see #removeItemListener
  331.      */
  332.     public synchronized void addItemListener(ItemListener l)
  333.     {
  334.         itemListener = AWTEventMulticaster.add(itemListener, l);
  335.     }
  336.  
  337.     /**
  338.      * Removes the specified Item listener so it no longer receives
  339.      * Item events from this component.
  340.      * @param l the action listener
  341.      * @see #addItemListener
  342.      */
  343.     public synchronized void removeItemListener(ItemListener l)
  344.     {
  345.         itemListener = AWTEventMulticaster.remove(itemListener, l);
  346.     }
  347.  
  348.     /**
  349.      * This is the Item Event handling innerclass.
  350.      */
  351.     class IL implements java.awt.event.ItemListener
  352.     {
  353.         /**
  354.          * Handles Item State Changed events
  355.          * @param e the ItemEvent
  356.          */
  357.         public void itemStateChanged(ItemEvent e)
  358.         {
  359.             sourceItemEvent((Checkbox) e.getSource());
  360.         }
  361.     }
  362.  
  363.     /**
  364.      * This is the PropertyChangeEvent handling inner class for the constrained SelectedRadioButtonIndex property.
  365.      * Handles vetoing SelectedRadioButtonIndex indexes that are not valid.
  366.      */
  367.     class IV implements java.beans.VetoableChangeListener, java.io.Serializable
  368.     {
  369.         /**
  370.          * This method gets called when an attempt to change the constrained Frame property is made.
  371.          * Ensures the given Frame string is valid for this button.
  372.          *
  373.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  374.          *             event source and the property that has changed.
  375.          * @exception PropertyVetoException if the recipient wishes the property
  376.          *              change to be rolled back.
  377.          */
  378.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  379.         {
  380.             int i = ((Integer)e.getNewValue()).intValue();
  381.             if (!isValidSelectedRadioButtonIndex(i))
  382.             {
  383.                 throw new PropertyVetoException(errors.getString("InvalidSelectedRadioButtonIndex") + i, e);
  384.             }
  385.         }
  386.     }
  387.  
  388.     /**
  389.      * Is the given index value valid.
  390.      * @param index the given index to test
  391.      * @return true if the given index is acceptable, false if not.
  392.      * To be valid it has to be within the limits of the rbList:
  393.      */
  394.     protected boolean isValidSelectedRadioButtonIndex(int index)
  395.     {
  396.         if(rbList != null && index < rbList.size() && index >= 0)
  397.             return true;
  398.         else
  399.             return false;
  400.     }
  401.  
  402.     /**
  403.      * Fires an item event to the listeners.
  404.      * @param item the radio button that changed state
  405.      */
  406.     protected void sourceItemEvent(Checkbox item)
  407.     {
  408.         if(item != lastItem)
  409.         {
  410.             if (itemListener != null)
  411.                 itemListener.itemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, item, (item.getState() ? ItemEvent.SELECTED : ItemEvent.DESELECTED)));
  412.             lastItem = item;
  413.         }
  414.     }
  415.  
  416.     protected void addImpl(Component component, Object constraints, int index)
  417.     {
  418.         moveIntoGroup(component);
  419.  
  420.         super.addImpl(component,constraints,index);
  421.         if(isValidSelectedRadioButtonIndex(tempSelectionIndex))
  422.             try { setSelectedRadioButtonIndex(tempSelectionIndex); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
  423.  
  424.     }
  425.  
  426.     protected void moveIntoGroup(Component component)
  427.     {
  428.         if(!(component instanceof Checkbox))
  429.         {
  430.             return;
  431.         }
  432.  
  433.         //Cast the component to a checkbox
  434.         Checkbox checkBox = ((Checkbox)component);
  435.  
  436.         //Save the state
  437.         boolean savedState = checkBox.getState();
  438.  
  439.         //Set up the checkbox group
  440.         checkBox.setCheckboxGroup(group);
  441.  
  442.         //Restore the state if it was true
  443.         if (savedState)
  444.             checkBox.setState(savedState);
  445.  
  446.         checkBox.addItemListener(item);
  447.  
  448.         //Keep the component in our internal vector.
  449.         rbList.addElement(checkBox);
  450.     }
  451.  
  452.     protected CheckboxGroup group;
  453.     /**
  454.      * Vector of Checkboxes added to the panel.  Used to set selected RadioButton by index.
  455.      */
  456.     protected Vector    rbList;
  457.     protected ItemListener itemListener = null;
  458.     protected int tempSelectionIndex;
  459.     /**
  460.      * is the component added to a container hierarchy?
  461.      */
  462.     protected boolean   isAdded = false;
  463.     transient protected ResourceBundle errors;
  464.  
  465.     private IL            item        = null;
  466.     private IV            indexVeto    = null;
  467.     private Checkbox    lastItem    = null;
  468.     private symantec.itools.beans.VetoableChangeSupport vetos = new symantec.itools.beans.VetoableChangeSupport(this);
  469.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  470. }
  471.  
  472.