//////////////////////////////////////////////////
// TabbedPanel
// A panel capable of displaying one of many components at a time. 
// The component to display is chosen by a row of tab buttons.
package gui;
import java.awt.*;
import java.util.*;
/////////////////////////////////////////////////
public class TabbedPanel extends Panel {
private TabSelector tab;	// Component for choosing panel.
private TabbedDisplayPanel disp; // Where other panels are displayed.
private Hashtable htComponents = new Hashtable(); // Keeps components indexed
                                                  // by their names. 
private Color hi = new Color(230,230,230);
private Color lo = new Color(50,50,50);
  //------------------------------------------------
public TabbedPanel() {
  setLayout(new BorderLayout());
  tab = new TabSelector(hi, lo);
  disp = new TabbedDisplayPanel(hi, lo);
  add("Center", disp);
}
  //------------------------------------------------
public TabbedPanel(Color TabBackground) {
  setLayout(new BorderLayout());
  tab = new TabSelector(hi, lo, TabBackground);
  disp = new TabbedDisplayPanel(hi, lo);
  add("Center", disp);
}
  //------------------------------------------------
public void addItem(String n, Component c) {
  // PROMISES: Add a component to be chosen by a tab with the 
  // given name.
  htComponents.put(n, c);
  tab.addItem(n);
  disp.addItem(n, c); 
  if(htComponents.size() == 2) {
    add("North", tab);
    validate();
  }
}
  //------------------------------------------------
public void removeItem(String ItemName) {
  Component c = (Component)htComponents.get(ItemName);
  if(c != null) {
    tab.removeItem(ItemName);
    disp.removeItem(c);
    htComponents.remove(ItemName);
    if(htComponents.size() == 1) {
      remove(tab);
      validate();
    }
  }
}
  //------------------------------------------------
public void select(String n) {
  // PROMISES: Display a component in the panel.
  tab.choose(n);
  disp.choose(n);
}
  //------------------------------------------------
  Dimension preferredSizeOfDisplayPanel() {
    return(new Dimension(size().width, size().height-tab.size().height));
  }
  //------------------------------------------------
void chose(String n) {
  // PROMISES: Called back by a TabSelector object when the user 
  // clicks on a tab.
  disp.choose(n);
}
  //------------------------------------------------
}
//////////////////////////////////////////////////
class TabSelector extends Canvas {
private Color hi, lo;
private Vector name = new Vector();
private int chosen = 0;
private Font font = new Font("Helvetica", Font.BOLD, 12);
private int HeightOfTabPanel = 40;
private int xBreathingSpaceOnTab = 30; // Space on each side of the tab string.
private int yBreathingSpaceOnTab = 10; // Space above and below the tab string.
  //------------------------------------------------
  TabSelector(Color h, Color l) {
    hi = h; lo = l;
  }
  //------------------------------------------------
  TabSelector(Color h, Color l, Color TabBackground) {
    this(h, l);
    setBackground(TabBackground);
  }
  //------------------------------------------------
  void addItem(String n) {
    name.addElement(n);
    if(name.size() == 2)
      show();
    else if(name.size() > 2)
      paint(getGraphics());
  }
  //------------------------------------------------
  void removeItem(String n) {
    name.removeElement(n);
    if(name.size() < 2)
      hide();
    else
      paint(getGraphics());
  }
  //------------------------------------------------
  void choose(String n) {
    for(int i=0; i<name.size(); ++i)
      if (((String)name.elementAt(i)).equals(n)) {
	chosen = i;
	paint(getGraphics());
      }
  }
  //------------------------------------------------
public Dimension preferredSize() {
  return minimumSize();
}
  //------------------------------------------------
public Dimension minimumSize() {
  Graphics g = getGraphics();
  if(g == null) 
    HeightOfTabPanel = 25;
  else
    HeightOfTabPanel = g.getFontMetrics().getHeight() + 2*yBreathingSpaceOnTab;
  
  return (new Dimension(getParent().size().width, HeightOfTabPanel));
}
  //------------------------------------------------
public void paint(Graphics g) {
  if(g == null)
    return;
  super.paint(g);
  if(name.size() < 2)
    return;
  g.setColor(getForeground());
  int th = size().height;
  int xMax = size().width;

  g.setFont(font);
  FontMetrics fm = g.getFontMetrics();
  int x=0; int y=th-yBreathingSpaceOnTab;
  for(int i=0; i<name.size(); ++i) {
    String str = (String)name.elementAt(i);
    int tw = fm.stringWidth(str) + 2*xBreathingSpaceOnTab;
    if (i == chosen) {
      g.setColor(lo);
      g.drawLine(x+tw-3, 4, x+tw-3, th-1);
      g.drawLine(x+tw-4, 5, x+tw-4, th-1);
      g.setColor(hi);
      g.drawLine(x, 3, x, th-1);
      g.drawLine(x+1, 3, x+1, th-1);
      g.drawLine(x, 3, x+tw-4, 3);
      g.drawLine(x, 4, x+tw-5, 4);
      g.drawLine(x+tw-3, th-1, x+tw-1, th-1);
      g.drawLine(x+tw-3, th-2, x+tw-1, th-2);
    }
    else {
      if(i+1 != chosen) {
        g.setColor(lo);
        g.drawLine(x+tw-3, 6, x+tw-3, th-1);
        g.drawLine(x+tw-4, 7, x+tw-4, th-1);
        g.setColor(hi);
        g.drawLine(x, 5, x+tw-4, 5);
        g.drawLine(x, 6, x+tw-5, 6);
      }
      else {
        g.setColor(hi);
        g.drawLine(x, 5, x+tw, 5);
        g.drawLine(x, 6, x+tw, 6);
      }
      g.drawLine(x, 5, x, th-1);
      g.drawLine(x+1, 5, x+1, th-1);
      g.drawLine(x, th-1, x+tw-1, th-1);
      g.drawLine(x, th-2, x+tw-1, th-2);
    }
    g.setColor(lo);
    g.drawString(str, x+xBreathingSpaceOnTab, y);
    x += tw;
  }
  g.setColor(hi);
  g.drawLine(x, th-1, xMax-1, th-1);
  g.drawLine(x, th-2, xMax-1, th-2);
}
  //------------------------------------------------
public boolean mouseUp(Event evt, int x, int y) {
  if (name.size() == 0) return false;
  int xCurr=0;
  boolean found = false;
  FontMetrics fm = getGraphics().getFontMetrics();
  for(int i=0; i<name.size() && !found; ++i) {
    int tw = fm.stringWidth((String)name.elementAt(i)) + 2*xBreathingSpaceOnTab;
    if(x>=xCurr && x<xCurr+tw) {
      chosen = i;
      found = true;
    }
    xCurr += tw;
  }
  ((TabbedPanel)getParent()).chose((String)name.elementAt(chosen));
  paint(getGraphics());
  return true;
}
  //------------------------------------------------
}
//////////////////////////////////////////////////
class TabbedDisplayPanel extends Panel {
  private int NumItems = 0;
  Color hi, lo;
  //------------------------------------------------
  TabbedDisplayPanel(Color h, Color l) {
    hi = h; lo = l;
    setLayout(new CardLayout());
  }
  //------------------------------------------------
  void addItem(String n, Component c) {
    // PROMISES: Add one component to the set of possibles to be shown.
    add(n, c);
    ++NumItems;
    if(NumItems == 2) {
      Graphics g = getGraphics();
      if(g != null) {
        g.setColor(getBackground());
        g.drawLine(0, 0, size().width, 0);
        g.drawLine(0, 1, size().width, 1);
      }
    }
    validate();
  }
  //------------------------------------------------
  void removeItem(Component c) {
    ((CardLayout)(getLayout())).removeLayoutComponent(c);
    --NumItems;
    validate();
  }
  //------------------------------------------------
  void choose(String n) {
    // PROMISES: Display the named panel.
    ((CardLayout)(getLayout())).show(this, n);
  }
  //------------------------------------------------
public Insets insets() {
  return new Insets(5, 5, 5, 5);
}
  //------------------------------------------------
public void paint(Graphics g) {
  if(g == null)
    return;
  super.paint(g);
  int w = size().width;
  int h = size().height;
  g.setColor(hi);
  g.drawLine(0, 0, 0, h-1);
  g.drawLine(1, 0, 1, h-1);

  if(NumItems < 2) {
    g.drawLine(0, 0, w, 0);
    g.drawLine(0, 1, w, 1);
  }
  g.setColor(lo);
  g.drawLine(0, h-1, w-1, h-1);
  g.drawLine(0, h-2, w-1, h-2);
  g.drawLine(w-1, 0, w-1, h-1);
  g.drawLine(w-2, 0, w-2, h-1);
}
  //------------------------------------------------
}
//////////////////////////////////////////////////


