/**
 * @version 1.0 Oct. 5, 2000
 * @author Ping Wang
 * @purpose of this program is to create a graphic editor which can be used to 
 * @draw (line, rectangle, filled rectangle, oval, filled oval,
 * @move, copy, resize, delete, clean screen...
 */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;


// create a class whose instance will hold both buttons 
// and MousePanel object
class ButtonPanel extends JPanel
	implements ActionListener
{
	//data members field
	//color for expected shapes, bg for buttons' background colour
	private Color color, bg;	 
	private MousePanel panel_right;

	//set original status for all of fuctional buttons
	private boolean b_draw = false, b_clear = false, 
					b_del = false, b_copy = false,
					b_move = false, b_resize = false,
					b_line = false, b_rect = false, 
					b_frect = false, b_oval = false,
					b_foval = false;
	//constructor
	public ButtonPanel()
	{

		setLayout(new BorderLayout(10,5));

		//add MousePanel object onto the right of the window
		panel_right = new MousePanel();
		panel_right.setBackground(Color.white);
		add(panel_right, "Center");

	
		//create and add new Panel object onto the left of the window
		JPanel panel_left = new JPanel();

		//separate panel_left into panel_left_top
		//and panel_left_bottom, to hold color selection buttons
		//and fuctional buttons, respectively
		panel_left.setLayout(new GridLayout(2,1,20,20));
		
		//add color selection buttons
		JPanel panel_left_top = new JPanel();
		panel_left_top.setLayout(new GridLayout(6,2,5,5));
		
		String[] buttons1 ={"red","blue","cyan","darkGray",
							"gray", "green","lightGray", "magenta",
							 "orange", "pink", "yellow","black"};

		for (int i = 0; i < buttons1.length; i++)
			{
				switch(i)
				{
					case 0: bg = Color.red; break;
					case 1: bg = Color.blue; break;
					case 2: bg = Color.cyan; break;
					case 3: bg = Color.darkGray; break;
					case 4: bg = Color.gray; break;
					case 5: bg = Color.green; break;
					case 6: bg = Color.lightGray; break;
					case 7: bg = Color.magenta; break;
					case 8: bg = Color.orange; break;
					case 9: bg = Color.pink; break;
					case 10: bg = Color.yellow; break;
					case 11: bg = Color.black; break;
					default: break;
				}
				addButton1(panel_left_top, buttons1[i], bg);
				System.out.println(buttons1[i]);
			}

		panel_left.add(panel_left_top, "North");

		                              
		//add functional buttons, move, resize, delete, etc...
		JPanel panel_left_bottom = new JPanel();
		panel_left_bottom.setLayout(new GridLayout(5,2,5,5));
		String[] buttons2 = {"line", "rect","frect","oval",  
							"foval","move","copy","del","resize","clear"};
		for (int i = 0; i < buttons2.length; i++)
			{
				addButton2(panel_left_bottom, buttons2[i]);
				System.out.println(buttons2[i]);
			}

   		panel_left.add(panel_left_bottom, "South");


		add(panel_left, "West");
	}

	//method to add color choice Buttons onto specific panel

	/**
	purpose:
	pre:
	post:
	*/
	private void addButton1(Container c, String s, Color l)
	{
		JButton b = new JButton(s);
		b.setBackground(l);
		c.add(b);
		b.addActionListener(this);
	}
	
	//method to add fuctional Buttons onto specific panel
	private void addButton2(Container c, String s)
	{
		JButton b = new JButton(s);
		
		c.add(b);
		b.addActionListener(this);
	}

	//get reponses, when button pressed,
	//then activate any methods or set any value  ...
	public void actionPerformed(ActionEvent evt)
	{	
		String s = evt.getActionCommand();
		
		//get response from color choice buttons
		if (s.equals("red"))
		{color = Color.red;}
		else if (s.equals("blue"))
		{color = Color.blue;}
		else if (s.equals("cyan"))
		{color = Color.cyan;}
		else if (s.equals("darkGray"))
		{color = Color.darkGray;}
		else if (s.equals("gray"))
		{color = Color.gray;}
		else if (s.equals("green"))
		{color = Color.green;}
		else if (s.equals("lightGray"))
		{color = Color.lightGray;}
		else if (s.equals("magenta"))
		{color = Color.magenta;}
		else if (s.equals("orange"))
		{color = Color.orange;}
		else if (s.equals("pink"))
		{color = Color.pink;}
		else if (s.equals("yellow"))
		{color = Color.yellow;}
		else if (s.equals("black"))
		{color = Color.black;}


      	else if (s.equals("move")) // press "move" button
     	{
     		b_draw = false;
			b_move = true;
			b_resize = false;
			b_copy = false;
     	}
        else if (s.equals("line")) // press "line" button
     	{
     	 	b_clear = false; b_move = false; b_del = false;
     	 	b_draw = true;b_line = true; b_rect = false; 
     	 	b_frect = false; b_oval = false; b_foval = false;
			b_resize = false;
     	}
     	else if (s.equals("rect")) // press "rect" button
        {	b_clear = false;b_move = false; b_del = false;
      		b_draw = true; b_line = false; b_rect = true; 
      		b_frect = false; b_oval = false; b_foval = false;
			b_resize = false;
        }
     	else if (s.equals("frect")) // press "frect" button
     	{	b_clear = false;b_move = false;	b_del = false;
     	 	b_draw = true;b_line = false; b_rect = false; 
    	 	b_frect = true; b_oval = false; b_foval = false;
			b_resize = false;
    	}
     	else if (s.equals("oval"))	// press "oval" button
     	{	b_clear = false;b_move = false;	b_del = false;
    	  	b_draw = true;b_line = false; b_rect = false; 
      		b_frect = false; b_oval = true; b_foval = false;
			b_resize = false;
    	}
  	    else if (s.equals("foval"))	 // press "foval" button
     	{	b_clear = false;b_move = false;	b_del = false;
    	  	b_draw = true;b_line = false; b_rect = false; 
    	  	b_frect = false; b_oval = false; b_foval = true;
			b_resize = false;
    	}
    	else if (s.equals("del"))	// press "del" button
    	{	b_draw = false; b_del = true; b_move = false;}
    	else if (s.equals("clear"))
    	{
    	  	b_draw = false;
			b_clear = true;
			b_move = false;
     	}
    	else if (s.equals("copy"))	 // press "copy" button
    	{
    		b_draw = false; 
    		b_copy = true;
			b_move = true;

    	}
    	else if (s.equals("resize"))  // press "resize" button
     	{
			b_resize = true;
			b_draw = false;
			b_move = false;
			b_copy = false;
			b_del = false;
     	}

		if(b_draw == true)
			b_copy = false;

		//set value for the panel_right's instance variables
      panel_right.set_Color(color);
	  panel_right.set_Status(b_draw, b_clear, b_move,b_del, 
	  					b_copy, b_resize, b_line, b_rect, 
	  					b_frect,b_oval, b_foval);

		//when "clear" button pressed, call MousePanel's setShapes()
		//method to clean the screen
		if (b_clear == true)
		{
			panel_right.setShapes();
		}

	}//end of ActionPerformed() method

}//end of ButtonPanel class




//class whose instance will be put onto the middle of the window
// to show all kinds of drawn shapes

class MousePanel extends JPanel
   implements MouseMotionListener
{  
   // data members field.
   //MAXNSHAPES--maximum shapes that can be held
   //all fuction status originally be signed as "false", and will be
   //changed accordingly after any button pressed events happen.
   //nshapes---the number of the object held in the array "shapes"
   //leftX, topY, dragX, dragY, width, height, rightX, bottomY---
   //----those are parameters needed for drawing shapes 
   private static final int MAXNSHAPES = 10000;
   private int current = -1;
   private boolean  b_line = false, b_oval = false, b_rect = false, 
   					b_foval = false, b_frect = false;
   private Color color;
   private boolean b_draw = false, b_clear = false,b_resize = false, 
   					b_move = false, b_del = false, b_copy = false;
   private int nshapes =0;
   private MyShape[] shapes = new MyShape[MAXNSHAPES];
   private MyShape temp;
   private int leftX, topY, dragX, dragY, width, height, rightX, bottomY;

	//constructor
   public MousePanel()
   {
      addMouseListener(new MouseAdapter() 
      { public void mousePressed(MouseEvent evt)//what to do when mouse 
         {  									//is pressed
         	int x = evt.getX();
         	int y = evt.getY();

	        //if (current < 0),mouse not inside any shape's area
           	//if (current >0), mouse inside one of shape
            current = find(x, y);

			//add "del" function
			if (b_del == true)
				remove(current);
			//get mouse coordinates
            if (b_draw == true  )
			{
				dragX = leftX = x;
				dragY = topY = y ;
			}

			//add "copy" fuction
			if (b_copy == true)
			{

		 		add(shapes[current].leftX+5,shapes[current].topY+10,
		 			shapes[current].rightX+5 ,shapes[current].bottomY+10,
		 			shapes[current].width,shapes[current].height);
 
			}

         }
			 //what to do when mouse released
		public void mouseReleased(MouseEvent evt)
		{
			int x = evt.getX();
			int y = evt.getY();
			
			//get coordinates and shape parameter 
			//for line or other shapes
			if (b_line)
			{
				rightX = x;
				bottomY = y;
				width = Math.abs(rightX-leftX);
				height = Math.abs(topY-bottomY);	
			}
			else
			{

				if ( x < dragX)
				{
					width = dragX-x;
					leftX = x;
					rightX = dragX;
				}	
				else {width = x - leftX; 
					rightX = x;
				}
				if (y < dragY)
				{
					height = dragY - y;
					topY = y;
					bottomY = dragY;
				}
				else {height = y - topY;
					bottomY = y;
				}

            }

			//add the shape onto the screen, also save the object 
			//in the array shapes
			if (b_draw == true)
			add(leftX, topY, rightX, bottomY, width, height);
			
		}

      });
		//get reponse when mouse moves
      addMouseMotionListener(this);
   }  //end of the constructor

   //locate the mouse, and decide if it in the area 
   // of one object
   public int find(int x, int y)
   {  for (int i = 0; i < nshapes; i++)
         if 
         (
         	((shapes[i].leftX <= x && x <= shapes[i].rightX)||
         	(shapes[i].rightX <= x && x <= shapes[i].leftX))&& 
         	((shapes[i].topY <= y && y <= shapes[i].bottomY)||
		 	(shapes[i].bottomY <= y && y <= shapes[i].topY))
		  )
            return i;
      return -1;
   }

   //add object into the array and call repaint to do the 
   //screen freshing 
   public void add(int leftX, int topY, int rightX, 
   					int bottomY, int width, int height)
   {  if (nshapes < MAXNSHAPES)
      {  shapes[nshapes] = new MyShape(color, leftX, topY, 
      						width, height, rightX, bottomY );
         current = nshapes;
         nshapes++;
		 shapes[current].set_Status(b_line, b_rect, b_frect, b_oval, b_foval);
         repaint();
      }
   }
	
   //method used to draw all objects	
   public void paintComponent(Graphics g)
   {  
			super.paintComponent(g);
         	for (int i = 0; i < nshapes; i++)
         	shapes[i].display(g);
   }
	//method for clean screen, can only be called when 
	//button "clear" pressed
	public void setShapes()
	{
		nshapes = 0;
		repaint();
	}
	
	//method to remove object from array and 
	//call repaint() to freshing screen 
   public void remove(int n)
   {  if (n < 0 || n >= nshapes) return;
      nshapes--;
      shapes[n] = shapes[nshapes];
      if (current == n)    
      current = -1;
      repaint();
   }
   //what to do when mouse moving, answer is to 
   //change the looking of the mouse cursor
   public void mouseMoved(MouseEvent evt) 
   {  int x = evt.getX();
      int y = evt.getY();

      if ((find(x, y) >= 0)) 
         setCursor(Cursor.getPredefinedCursor
            (Cursor.CROSSHAIR_CURSOR)); 
      else 
         setCursor(Cursor.getDefaultCursor());
   }

   //what to when mouse dragged
   public void mouseDragged(MouseEvent evt) 
   {  int x = evt.getX();
      int y = evt.getY();
   
	  //get coordinates and shape parameters for line or other shapes
			if (b_line)
			{
				rightX = x;
				bottomY = y;
				width = Math.abs(rightX-leftX);
				height = Math.abs(topY-bottomY);	
			}
			else
			{
				if ( x < dragX)
				{
					width = dragX-x;
					leftX = x;
					rightX = dragX;
				}	
				else {width = x - leftX; 
					rightX = x;
				}
				if (y < dragY)
				{
					height = dragY - y;
					topY = y;
					bottomY = dragY;
				}
				else {height = y - topY;
					bottomY = y;
				}
			}
	  // show the temporary shapes drawn when mouse is dragged
	  // and those objects will not saved into array
			if (b_draw == true)
			{	repaint();
				Graphics g = getGraphics();
				temp = new MyShape(color, leftX, topY, 
      						width, height, rightX, bottomY);
				temp.set_Status(b_line, b_rect, b_frect, b_oval, b_foval);
				temp.display(g);
			}

		//add resize fuction
      if ((current >=0)&&(b_resize == true))
      {  Graphics g = getGraphics();
         g.setXORMode(getBackground());
		 shapes[current].display(g);
		 
		 shapes[current].rightX = x;
		 shapes[current].bottomY = y;

         shapes[current].width = Math.abs(x-shapes[current].leftX);
         shapes[current].height = Math.abs(y-shapes[current].topY);
		 repaint();

      }
				
		// add move fuction		
		if ((current >= 0)&&(b_move == true)&&(b_draw == false))
		{
		     Graphics g = getGraphics();
            g.setXORMode(getBackground());
			 shapes[current].display(g);
		 
			 shapes[current].rightX = shapes[current].rightX 
		 						+ (x-shapes[current].leftX);
			 shapes[current].bottomY = shapes[current].bottomY 
			 						+ (y-shapes[current].topY);

       		  shapes[current].leftX = x;
       		  shapes[current].topY = y;
	   		 repaint();	
			
		}
			

   }
   //  set color value
   public void set_Color(Color color)
   {
      this.color = color;
   }
	// set flags for each status 
	public void set_Status(boolean b_draw, boolean b_clear,boolean b_move, 
						boolean b_del, boolean b_copy, boolean b_resize,
						boolean b_line, boolean b_rect,boolean b_frect, 
						boolean b_oval, boolean b_foval)
	{
		this.b_draw = b_draw;
		this.b_resize = b_resize;
		this.b_clear = b_clear;
		this.b_del = b_del;
		this.b_copy = b_copy;
		this.b_move = b_move;
		this.b_line = b_line;
		this.b_rect = b_rect;
		this.b_frect = b_frect;
		this.b_oval = b_oval;
		this.b_foval = b_foval;
	}


}//end of MousePanel class

	






// class MyShape used to display diferent shapes,
// line, rectangle, filled rectangle, oval, filled oval
class MyShape
{
	//data memeber fields
	//leftX, topX, width, height, rightX, bottomY
	//----shape parameters
	//b_line, b_rect, b_frect, b_oval, b_foval
	//----flags used to select a shape
	public int leftX, topY, width, height, rightX, bottomY;
	private Color color;
	private boolean b_line, b_rect, b_frect, b_oval, b_foval;

	//constructor
	public MyShape(Color color, int leftX, int topY, int width, 
					int height, int rightX, int bottomY )
	{
		this.color = color;
		this.leftX = leftX;
		this.topY = topY;
		this.width = width;
		this.height = height;
		this.rightX = rightX;
		this.bottomY = bottomY;
	}
	
	//method to set color variable value
	public void set_Color(Color color)
	{
		this.color = color;
	}
	
	//method to set status variable value
	public void set_Status(boolean b_line, boolean b_rect,
							 boolean b_frect, boolean b_oval, 
							 boolean b_foval)
	{
		this.b_line = b_line;
		this.b_rect = b_rect;
		this.b_frect = b_frect;
		this.b_oval = b_oval;
		this.b_foval = b_foval;
	}

	//method used to display individual shape,
	//(line, rect, filled-rect, oval, filled-oval)
	public void display(Graphics g)
	{    	
    	g.setColor(color);
    	if(b_line == true)
    		g.drawLine(leftX, topY, rightX, bottomY);
    	else if (b_rect == true)
    		g.drawRect(leftX, topY, width, height);
    	else if (b_frect == true)
    		g.fillRect(leftX, topY, width, height);
    	else if (b_oval == true)
    		g.drawOval(leftX, topY, width, height);
 		else if (b_foval == true)
    		g.fillOval(leftX, topY, width, height);
	}

} //end of MyShape class













public class GraphicEditor extends JApplet
{
	public void init()
	{
		Container contentPane = getContentPane();
		contentPane.add(new ButtonPanel());
	}
 } //end of GraphicEditor8 class

