import java.awt.*;
import java.awt.event.*;

/**
 * The drawPanel class manages the actual whiteboard, as well as sending and 
 * processing messages from the server.
 *
 * @author Johan Andersen
 * @version $Revision: 1.6 $
 * 
 * @see Frame
 * @see whiteBoard
 * @see whiteCanvas
 *
 */

class drawPanel extends Frame implements WindowListener, MouseMotionListener, 
	    ItemListener, MouseListener, ActionListener
{
  /** A pointer to our network connection */
  private ClientSocket socket;

  /** A pointer to our parent */
  private whiteBoard our_parent;

  /** The canvas we will be drawing on */
  private whiteCanvas c;

  /** The previous point recorded */
  private Point lastPoint = null;

  /** whether we are allowed to draw to the whieBoard */
  private boolean canDraw = false;

  /** A choice of available colors */
  private Choice colors;

  /** A choice of tools */
  private Choice tools;

  /** A choice of available thicknesses */
  private Choice sizes;

  /** The current color we are drawing in */
  private Color curColor = Color.black;

  private Button clearButton;

  private void add(Component c, GridBagLayout gbl, GridBagConstraints gbc,
                   int x, int y, int w, int h)
  {
    gbc.gridx = x;
    gbc.gridy = y;
    gbc.gridwidth = w;
    gbc.gridheight = h;
    gbl.setConstraints(c, gbc);
    add(c);
  }

  /**
   * Constructor
   *
   * @param p the whiteBoard object that controls this panel
   * @param x the width of the canvas
   * @param y the height of the canvas
   */
  public drawPanel(whiteBoard p, int x, int y)
  {
    our_parent = p;
    c = new whiteCanvas();

    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();

    gbc.weightx = 0;
    gbc.weighty = 0;
    gbc.insets  = new Insets(2,2,2,2);
    gbc.fill    = GridBagConstraints.BOTH;
    setLayout(gbl);

    setLayout(gbl);

    c.setSize(x,y);
    c.addMouseMotionListener(this);
    c.addMouseListener(this);
    add(c,gbl,gbc,0,0,4,3);

    add(new Label("Color", Label.CENTER),gbl,gbc,0,3,1,1);
    add(new Label("Tool", Label.CENTER),gbl,gbc,1,3,1,1);
    add(new Label("Size",Label.CENTER),gbl,gbc,2,3,1,1);
    
    clearButton = new Button("Clear");
    clearButton.addActionListener(this);
    colors = new Choice();
    
    colors.add("Black");
    colors.add("Blue");
    colors.add("Red");
    colors.add("Green");
    colors.add("Erase");
    colors.addItemListener(this);

    tools = new Choice();

    tools.add("Line");
    tools.add("Rectangle");
    tools.add("Circle");

    sizes = new Choice();

    sizes.add("1");
    sizes.add("4");
    sizes.add("8");
    sizes.add("12");
    sizes.add("Solid");
    sizes.addItemListener(this);

    add(colors,gbl,gbc,0,4,1,1);
    add(tools,gbl,gbc,1,4,1,1);
    add(sizes,gbl,gbc,2,4,1,1);
    gbc.fill    = GridBagConstraints.NONE;
    add(clearButton,gbl,gbc,3,3,1,2);
    clearButton.setEnabled(false);
    pack();
  }

  /**
   * Function to clear the white board
   */
  void clear()
  {
    c.clear();
    our_parent.socket.send("all","clear","");
  }

  /**
   * Function called  by the network to clear the whiteboard (Does not issue
   * a clear request over the network)
   */
  public void erase()
  {
    c.clear();
  }

  /**
   * Function to allow/disallow the user to draw to the whiteboard and clear
   * it.
   *
   * @param x true to be allowed to draw, false to disallow drawing
   *
   */
  public void setDrawable(boolean x)
  {
    canDraw = x;
    clearButton.setEnabled(x);
  }

  /**
   * Function called when the user closes this window
   */

  private void doQuit()
  {
    our_parent.doQuit();
  }

  public void windowClosed(WindowEvent event)
  {
  }

  public void windowDeiconified(WindowEvent event)
  {
  }

  public void windowIconified(WindowEvent event)
  {
  }

  public void windowActivated(WindowEvent event)
  {
  }

  public void windowDeactivated(WindowEvent event)
  {
  }

  public void windowOpened(WindowEvent event)
  {
  }
  
  public void windowClosing(WindowEvent event)
  {
    doQuit();
  }

  int last_x = -1;
  int last_y = -1;
  int last_w = -1;
  int last_h = -1;

  public void mouseDragged(MouseEvent e)
  {
    if ((canDraw) && (lastPoint != null)) {
      if (tools.getSelectedItem().equals("Line")) { //Start drawing now
	c.drawLine(lastPoint.x, lastPoint.y, e.getPoint().x, e.getPoint().y);

	our_parent.socket.send("all","line", lastPoint.x + "," + lastPoint.y 
			       + "," + e.getPoint().x + "," +
			       e.getPoint().y + "," + c.getThickness() + "," + 
			       curColor.getRed() + "," +
			       curColor.getGreen() + "," +
			       curColor.getBlue());
	
	lastPoint = e.getPoint();

       
      } else { //Else it's a shape, draw a temporary bounding rect
	Graphics g = c.getGraphics();
	int x, y, w, h;

	g.setXORMode(Color.orange);

	if (last_x != -1) {
	  g.drawRect(last_x,last_y,last_w,last_h);
	}

	w = lastPoint.x - e.getPoint().x;
	h = lastPoint.y - e.getPoint().y;
	if (w<0) { w *= -1; }
	if (h<0) { h *= -1; }

	if (lastPoint.x < e.getPoint().x) {
	  x = lastPoint.x;
	} else {
	  x = e.getPoint().x;
	}

	if (lastPoint.y > e.getPoint().y) {
	  y = e.getPoint().y;
	} else {
	  y = lastPoint.y;
	}

	g.drawRect(x,y,w,h);
	last_x = x;
	last_y = y;
	last_w = w;
	last_h = h;
      }
    }
  }

  public void drawLine(int x1, int y1, int x2, int y2, int thickness, Color x)
  {
    int tmp;
    c.setColor(x);
    tmp = c.getThickness();
    c.setThickness(thickness);
    c.drawLine(x1,y1,x2,y2);
    c.setColor(curColor);
    c.setThickness(tmp);
  }

  public void drawRect(int x1, int y1, int w, int h, int thickness, Color x)
  {
    int tmp;
    c.setColor(x);
    tmp = c.getThickness();
    c.setThickness(thickness);
    c.drawRect(x1,y1,w,h);
    c.setColor(curColor);
    c.setThickness(tmp);
  }

  public void drawCircle(int x1, int y1, int w, int h, int thickness, Color x)
  {
    int tmp;
    c.setColor(x);
    tmp = c.getThickness();
    c.setThickness(thickness);
    c.drawOval(x1,y1,w,h);
    c.setColor(curColor);
    c.setThickness(tmp);
  }


  public void mouseMoved(MouseEvent e)
  {
  }

  public void mouseClicked(MouseEvent e)
  {
  }

  public void mousePressed(MouseEvent e)
  {
    if (canDraw) {
      lastPoint = e.getPoint();
    }
  }

  public void mouseReleased(MouseEvent e)
  {
    Graphics g = getGraphics();

    if (last_x != -1) {
      g.setColor(Color.white);
      g.drawRect(last_x,last_y,last_w,last_h);
    }

    if (tools.getSelectedItem().equals("Rectangle")) {
      c.drawRect(last_x, last_y, last_w, last_h);
      our_parent.socket.send("all","rectangle", last_x + "," + last_y + "," + 
			     last_w + "," + last_h + "," + 
			     c.getThickness() + "," + 
			     curColor.getRed() + "," +
			     curColor.getGreen() + "," +
			     curColor.getBlue());

    } else if (tools.getSelectedItem().equals("Circle")) {
      c.drawOval(last_x,last_y,last_w,last_h);
      our_parent.socket.send("all","circle", last_x + "," + last_y + "," + 
			     last_w + "," + last_h + "," + 
			     c.getThickness() + "," + 
			     curColor.getRed() + "," +
			     curColor.getGreen() + "," +
			     curColor.getBlue());


    }

    lastPoint = null; //Clear last point
  }

  public void mouseEntered(MouseEvent e)
  {
  }

  public void mouseExited(MouseEvent e)
  {
  }

  public void itemStateChanged(ItemEvent e)
  {
    Object src = e.getSource();
    String s;
    
    if (src == colors) { //Set a new color
      s = colors.getSelectedItem();
      if (s.equals("Black")) {
	c.setColor(Color.black);
	curColor = Color.black;
      } else if (s.equals("Blue")) {
	c.setColor(Color.blue);
	curColor = Color.blue;
      } else if (s.equals("Green")) {
	c.setColor(Color.green);
	curColor = Color.green;
      } else if (s.equals("Red")) {
	c.setColor(Color.red);
	curColor = Color.red;
      } else if (s.equals("Erase")) {
	c.setColor(Color.white);
	curColor = Color.white;
      }
    } else if (src == sizes) { //Set a new Size
      s = sizes.getSelectedItem();
      if (s.equals("1")) {
	c.setThickness(1);
      } else if (s.equals("4")) {
	c.setThickness(2);
      } else if (s.equals("8")) {
	c.setThickness(5);
      } else if (s.equals("12")) {
	c.setThickness(10);
      } else if (s.equals("Solid")) {
	c.setThickness(-1);
      }
    }
  }

  public void actionPerformed(ActionEvent event)
  {
    Object src = event.getSource();

    if (src==clearButton) {
      clear();
    }
  }
}


