package brainydraw;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.applet.Applet;
import java.util.Vector;
import java.util.Enumeration;

interface Shape extends Serializable {
  public void draw(Graphics g);
}

class Rectangle implements Shape {

  int x1, y1, x2, y2;

  public Rectangle(int x1, int y1, int x2, int y2) {
    this.x1 = x1 < x2? x1 : x2;
    this.y1 = y1 < y2? y1 : y2;
    this.x2 = x1 < x2? x2 : x1;
    this.y2 = y1 < y2? y2 : y1;
  }

  public void draw(Graphics g) {
    g.setColor(Color.green);
    g.fill3DRect(x1, y1, x2 - x1, y2 - y1, true);
    //g.drawRect(x1, y1, x2 - x1, y2 - y1);
  }
} // end of class Rectangle

class Line implements Shape {

  int x1, y1, x2, y2;

  public Line(int x1, int y1, int x2, int y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
  }

  public void draw(Graphics g) {
    g.setColor(Color.red);
    g.drawLine(x1, y1, x2, y2);
  }
} // end of class Line

class Oval implements Shape {

  int x1, y1, x2, y2;

  public Oval(int x1, int y1, int x2, int y2) {
    this.x1 = x1 < x2? x1 : x2;
    this.y1 = y1 < y2? y1 : y2;
    this.x2 = x1 < x2? x2 : x1;
    this.y2 = y1 < y2? y2 : y1;
  }

  public void draw(Graphics g) {
    g.setColor(Color.yellow);
    g.fillOval(x1, y1, x2 - x1, y2 - y1);
    //g.drawOval(x1, y1, x2 - x1, y2 - y1);
  }
} // end of class Oval

class PanelApplet extends Applet {

  Vector shapes = new Vector();

  public void paint(Graphics g) {
    Enumeration e = shapes.elements();
    while (e.hasMoreElements()) {
      Shape s = (Shape) e.nextElement();
      s.draw(g);
    }
  }
} // end of PanelApplet class

public class BrainyDraw extends Frame
  implements ActionListener, ItemListener, MouseListener {

  int x1, x2, y1, y2;
  PanelApplet panel;
  String shapeType = "Rectangle";
  String filename = "draw.out";

  public BrainyDraw() {
    super("Brainy Draw");
    setLayout(null);

    // make a top level File and Edit menus
    Menu fileMenu = new Menu("File");
    Menu editMenu = new Menu("Edit");

    // create menu items for the File menu
    MenuItem newMenuItem = new MenuItem("New");
    MenuItem openMenuItem = new MenuItem("Open");
    MenuItem saveMenuItem = new MenuItem("Save");
    MenuItem exitMenuItem = new MenuItem("Exit");

    // create menu item for the Edit menu
    MenuItem undoMenuItem = new MenuItem("Undo");

    // add menu items to the File menu
    fileMenu.add(newMenuItem);
    fileMenu.add(openMenuItem);
    fileMenu.add(saveMenuItem);
    fileMenu.add(exitMenuItem);

    // add menu items to the Edit menu
    editMenu.add(undoMenuItem);

    // add ActionListener to File menu items
    newMenuItem.addActionListener(this);
    openMenuItem.addActionListener(this);
    saveMenuItem.addActionListener(this);
    exitMenuItem.addActionListener(this);

    // add ActionListener to Edit menu item
    undoMenuItem.addActionListener(this);

    // make a menu bar for this frame
    // and add top level menus File and Edit
    MenuBar mb = new MenuBar();
    setMenuBar(mb);
    mb.add(fileMenu);
    mb.add(editMenu);

    // add check box group
    CheckboxGroup cbg = new CheckboxGroup();
    Checkbox line = new Checkbox("Line", cbg, true);
    Checkbox oval = new Checkbox("Oval", cbg, true);
    Checkbox rectangle = new Checkbox("Rectangle", cbg, true);

    line.addItemListener(this);
    oval.addItemListener(this);
    rectangle.addItemListener(this);
    add(line);
    add(oval);
    add(rectangle);
    line.setBounds(5, 45, 75, 20);
    oval.setBounds(80, 45, 75, 20);
    rectangle.setBounds(155, 45, 475, 20);

    panel = new PanelApplet();
    add(panel);
    panel.setBounds(7, 70, 486, 422);
    panel.setVisible(true);
    panel.setBackground(Color.white);
    panel.addMouseListener(this);

    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent we) {
        System.exit(0);
      }
    });
  }
  public static void main(String[] args) {
    BrainyDraw win = new BrainyDraw();
    win.show();
    win.setSize(500, 500);
    win.setBackground(Color.gray);
  }

  private void save() {
    try {
      ObjectOutputStream out =
        new ObjectOutputStream(
          new FileOutputStream(filename));
      out.writeObject(panel.shapes);
      out.close(); // Also flushes output
    } 
    catch(Exception e) {
      e.printStackTrace();
    }
  }

  private void open() {
    try {
      ObjectInputStream in =
        new ObjectInputStream(
          new FileInputStream(filename));
      panel.shapes = (Vector)in.readObject();
      panel.repaint();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

  private void openNew() {
    panel.shapes.removeAllElements();
    panel.repaint();
  }

  private void undo() {
    int shapeCount = panel.shapes.size();
    if (shapeCount!=0) {
      panel.shapes.removeElementAt(shapeCount-1);
      panel.repaint();
    }
  }

  public void actionPerformed(ActionEvent ae) {
    String command = ae.getActionCommand().toString();

    if (command.equals("Exit"))
      System.exit(0);
    else if (command.equals("New"))
      openNew();
    else if (command.equals("Open"))
      open();
    else if (command.equals("Save"))
      save();
    else if (command.equals("Undo"))
      undo();
  }

  public void itemStateChanged(ItemEvent ie) {
    shapeType = ((Checkbox)ie.getItemSelectable()).getLabel();
  }
  public void mouseClicked(MouseEvent me) {
  }
  public void mouseEntered(MouseEvent me) {
  }
  public void mouseExited(MouseEvent me) {
  }
  public void mousePressed(MouseEvent me) {
    x1 = me.getX();
    y1 = me.getY();
  }
  public void mouseReleased(MouseEvent me) {
    x2 = me.getX();
    y2 = me.getY();
    Shape s = null;
    if (shapeType.equals("Rectangle")) {
      // a Rectangle cannot have a zero width or height
      if (x1!=x2 || y1!=y2)
        s = new Rectangle(x1, y1, x2, y2);
    }
    else if (shapeType.equals("Line")) {
      // a Rectangle cannot have a zero width or height
      if (x1!=x2 && y1!=y2)
        s = new Line(x1, y1, x2, y2);
    }
    else if (shapeType.equals("Oval")) {
      // an Oval cannot have a zero width or height
      if (x1!=x2 || y1!=y2)
        s = new Oval(x1, y1, x2, y2);
    }
    if (s!=null) {
      panel.shapes.add(s);
      panel.repaint();
    }
  }
} // end of class BrainyDraw