package extensions.awt;
import java.awt.*;

/** Construct a outlined, title panel for checkboxes.
  * It is assumed that the panel will act as a
  * CheckboxGroup, i.e. radio group, unless specified
  * otherwise.  The default layout is horizonal.
  * @version 1.0.2
  * @author John Webster Small
  * @see extensions.awt.OutlinedPanel
  */
public class CheckboxGroupPanel extends OutlinedPanel
{
  private CheckboxGroup cbg;
  private GridBagLayout gridbag = null;
  private GridBagConstraints constraints = null;

  /** Horizonal pixel gap between checkbox and panel. */
  public static int hgap = 10;

  /** Vertical pixel gap between checkboxes. */
  public static int vgap = 0;

  /** If this is a radio group return underlying
    * CheckboxGroup.
    */
  public CheckboxGroup getCheckboxGroup()
    { return cbg; }

  /** Construct an outlined panel for checkboxes.
    * @param title title of outlined panel
    * @param radioGroup if true the checkboxes are
    *  contained within an underlying CheckboxGroup,
    *  otherwise they are independ checkboxes that
    *  are simply visually grouped within the outlined
    *  panel.
    */
  public CheckboxGroupPanel
    (String title, boolean radioGroup)
  {
    super(title);
    cbg = (radioGroup? new CheckboxGroup() : null);
  }

  /** Construct an outlined panel for checkboxes.
    * This panel is acting like a CheckboxGroup, i.e.
    * radio group.
    * @param title title of outlined panel
    */
  public CheckboxGroupPanel(String title)
    { this(title,true); }

  /**
    * @return Returns current checkbox only if this
    * is a radio group.
    */
  public Checkbox getCurrent()
    { return ((cbg == null)? null : cbg.getCurrent()); }

  /** Set current checkbox only if this is a
    * radio group.
    */
  public void setCurrent(Checkbox box)
  {
    if (cbg != null)
      cbg.setCurrent(box);
  }

  /** Layout checkboxes vertically. */
  public void setVertical()
  {
    gridbag = new GridBagLayout();
    constraints = new GridBagConstraints();
    setLayout(gridbag);
    constraints.fill = GridBagConstraints.NONE;
    constraints.gridwidth = GridBagConstraints.REMAINDER;
    constraints.anchor = GridBagConstraints.WEST;
    constraints.insets = new Insets(vgap,hgap,vgap,hgap);
    for (int i = 0; i < countComponents(); i++)  {
      if (i > 0) // all but first
        constraints.insets = new Insets(0,hgap,vgap,hgap);
      gridbag.setConstraints(getComponent(i), constraints);
    }
    validate();
  }

  /** Layout checkboxes horizonally.  This is the
    * default layout.
    */
  public void setHorizonal()
  {
    setLayout(new FlowLayout(FlowLayout.CENTER,hgap,vgap));
    gridbag = null;
    constraints = null;
  }

  /* Not only set checkbox group but assign gridbag
     constraints if vertically oriented. */
  private boolean setCheckboxGroup(Component comp)
  {
    if (comp instanceof Checkbox)  {
      if (cbg != null)
        ((Checkbox)comp).setCheckboxGroup(cbg);
      if (gridbag != null)  {  // vertically oriented
        if (countComponents() > 1) // all but first
          constraints.insets = new Insets(0,hgap,vgap,hgap);
        gridbag.setConstraints(comp, constraints);
      }
      return true;
    }
    else  {
      new FrameExtended(new Exception
        (comp.getClass().getName()+" is not a Checkbox!"));
      return false;
    }
  }

  /** Only add the component to the panel if it is
    * a checkbox.
    * @param comp Checkbox to add to the panel
    * @return the component argument
    */
  public Component add(Component comp)
  {
    return (setCheckboxGroup(comp)? super.add(comp) : null);
  }

  /** Only add the component to the panel if it is
    * a checkbox.
    * @param comp Checkbox to add to the panel
    * @param pos the position at which to insert the
    *   component; or -1 to insert at the end 
    * @return the component argument
    */
  public Component add(Component comp, int pos)
  {
    return (setCheckboxGroup(comp)? super.add(comp,pos) : null);
  }

  /** Only add the component to the panel if it is
    * a checkbox.
    * @param comp Checkbox to add to the panel
    * @param name a tag understood by the layout manager
    *   but ignored in our case
    * @return the component argument
    */
  public Component add(String name, Component comp)
  {
    return (setCheckboxGroup(comp)? super.add(name,comp) : null);
  }
}
