package translate01;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.Shape.*;
import java.util.Random;

public class code extends JComponent 
	implements MouseListener, MouseMotionListener {
	
	private MyShape myShapes [] = new MyShape[4];
	private int mStartX, mStartY;  // for last mouse position
	private final AffineTransform minRotation = AffineTransform.getRotateInstance(Math.PI);
	
	public code(int windowWidth) { 
		// Listen for mouse movements and clicks
		addMouseMotionListener(this);
		addMouseListener(this);
		mStartX = 0;
		mStartY = 0; 
		
		// Initialize Shapes
		for (int im = 0; im < 4; im++) {
		// Place shapes along the diagonal
			myShapes[im] = new MyShape(im*windowWidth/4, im*windowWidth/4);  
		}
		
		myShapes[0].shape = new Rectangle2D.Double(myShapes[0].x0, myShapes[0].y0, windowWidth/5, windowWidth/5);
		myShapes[0].color = new Color(255, 0, 0); // red
		myShapes[1].shape = new Ellipse2D.Double(myShapes[1].x0, myShapes[1].y0, windowWidth/5, windowWidth/5);
		myShapes[1].color = new Color(0, 200, 200); // cyan
		myShapes[2].shape = new Arc2D.Double(myShapes[2].x0, myShapes[2].y0, windowWidth/5, windowWidth/5, 0, 270, Arc2D.PIE);
		myShapes[2].color = new Color(255, 150, 255); // light magenta
		myShapes[3].shape = new RoundRectangle2D.Double(myShapes[3].x0, myShapes[3].y0, windowWidth/5, windowWidth/5, windowWidth/25, windowWidth/25);
		myShapes[3].color = new Color(175, 0, 255); // violet
	}

	public void paint(Graphics g) {
		Graphics2D g2 = (Graphics2D)g;
		int wd = getSize().width;
		int ht = getSize().height;
		
		for (int im = 0; im < 4; im++) {	
			// draw the shape.  It is already transformed		
			g2.setColor(myShapes[im].color);
			g2.fill(myShapes[im].shape);
			//g2.setStroke(new BasicStroke(10));
			//g2.draw(myShapes[im].shape);
			g2.setColor(Color.black); // reset color to black
			
			//highlight selected Shape
			if (myShapes[im].selected) {
				g2.setPaint(Color.yellow);
				g2.setStroke(new BasicStroke(10));
				g2.draw(myShapes[im].shape); // we can draw the shape instead of the bounding rectangle				
				g2.setPaint(Color.black);
				g2.setStroke(new BasicStroke(1));
			}			
		}			
	}

	public void mouseDragged(MouseEvent e) {
		AffineTransform at = new AffineTransform();
		int xx = e.getX();
		int yy = e.getY();
		for (int im = 0; im < 4; im++) {
			if(myShapes[im].selected) {
				// at is the latest translation
				at.translate(xx - mStartX, yy - mStartY);
				
				// translate (x0, y0)
				myShapes[im].x0 += xx - mStartX;
				myShapes[im].y0 += yy - mStartY;
				
				// reset (mStartX, mStartY)
				mStartX = xx;
				mStartY = yy;
				
				// transform the shape by at
				myShapes[im].shape = at.createTransformedShape(myShapes[im].shape);
			}			
		}
		repaint();
	}

	public void mouseMoved(MouseEvent e) {
		int mods = e.getModifiers();
		AffineTransform at = new AffineTransform();
		
		for (int im = 0; im < 4; im++) {
			if(myShapes[im].selected) {
				if ((mods & InputEvent.SHIFT_MASK) != 0) {	
				// rotate counter-clockwise if shift is down
					// reset shape transform
					at.translate(myShapes[im].x0, myShapes[im].y0);
					at.rotate(Math.PI/6);
					at.translate(-myShapes[im].x0, -myShapes[im].y0);
					
					// transform the shape
					myShapes[im].shape = at.createTransformedShape(myShapes[im].shape);					
					}
				else if ((mods & InputEvent.CTRL_MASK) != 0) {
				// rotate clockwise if Ctrl is down
					at.translate(myShapes[im].x0, myShapes[im].y0);
					at.rotate(-Math.PI/6);
					at.translate(-myShapes[im].x0, -myShapes[im].y0);
					
					// transform shape
					myShapes[im].shape = at.createTransformedShape(myShapes[im].shape);
				}			
			}
		}		
		repaint();		
	}

	public void mousePressed(MouseEvent e) {
		mStartX = e.getX();
		mStartY = e.getY();
	}
	
	public void mouseReleased(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	
	public void mouseClicked(MouseEvent e) {
		int x, y;
		x = e.getX();
		y = e.getY();
				
		boolean selected = false;	// so at most one is selected below
		for (int im = 3; im >= 0; im--) {
			Point2D pt = new Point2D.Double(x, y);
			if (myShapes[im].shape.contains(pt)  && !selected) {
				myShapes[im].selected = true;
				selected = true;
			}
			else myShapes[im].selected = false;
		}
		repaint();
	}
	
	public static void main(String[] args){
		JFrame f = new JFrame("Select");
		int windowWidth = 600;
		Container c = f.getContentPane();
		c.setLayout(new BorderLayout());
		c.add(new code(windowWidth), BorderLayout.CENTER);
		f.setSize(windowWidth, windowWidth + 22);

		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e) { System.exit(0); }
		});

		f.setVisible(true);
	}
}