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

import javax.swing.*;

/**
 * This panel shows a large display area where MovingBall objects can
 * move.  Clicking on the display area creates a MovingBall.  There
 * are pop-up menus along the bottom of the panel that can be used
 * to select the color, size, and speed that will be used when balls
 * are created; changing the values in these menus has no effect on
 * balls that already exist.
 */
public class BallPenPanel extends JPanel {
	
	private MovingBall ball;  // The ball contained in the display (or null if there isn't one.)

	private Display display;  // The sub-panel where the ball moves.
	
	private JComboBox colorChoice;  // Pop-up menu to specify ball color.
	private final static Color[] colors =   // Colors corresponding to entries in the menu. 
	       { Color.RED, Color.GREEN, Color.BLUE, Color.CYAN, Color.MAGENTA, Color. YELLOW, Color.GRAY, Color.BLACK };
	
	private JComboBox sizeChoice;  // Pop-up menu to specify ball diameter.
	private final static int[] sizes = { 4, 6, 10, 14, 20, 26, 32, 50, 75, 100 };  // Sizes corresponding to menu entries.
	
	private JComboBox speedChoice;  // Pop-up menu to specify ball speed.
	private final static double[] speeds = { 2, 4, 6, 8, 10, 12, 15, 20}; // Speeds corresponding to menu entries.
	
	
	/**
	 * A class to represent the large display area in which the balls move.
	 */
	private class Display extends JPanel {
		Display() {
			setPreferredSize( new Dimension(500,500) );
			setBackground(Color.WHITE);
			addMouseListener(new MouseHandler());
			addComponentListener( new ComponentHandler());
		}
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			if (ball != null)
				ball.draw(g);
		}
	}
	
	
	/**
	 * A class to define a mouse listener that will create balls in response to
	 * clicks on the display.
	 */
	private class MouseHandler extends MouseAdapter {
		public void mousePressed(MouseEvent evt) {
			MovingBall newBall = new MovingBall(0,display.getWidth(),0,display.getHeight());
			newBall.setSpeed( speeds[speedChoice.getSelectedIndex()] );
			newBall.setRadius( sizes[sizeChoice.getSelectedIndex()] / 2 );
			newBall.setColor( colors[colorChoice.getSelectedIndex()] );
			newBall.setLocation(evt.getX(), evt.getY());
			ball = newBall;
			display.repaint();
		}
	}
	
	
	/**
	 * A class to define a component listener that will react to changes in the
	 * size of the display by changing the limits in which the balls move.  The
	 * limits correspond to the actual size of the display panel.
	 */
	private class ComponentHandler extends ComponentAdapter {
		public void componentResized(ComponentEvent evt) {
			if (ball != null)
				ball.setLimits(0, display.getWidth(), 0, display.getHeight());
		}
	}
	
	
	/**
	 * A class to define an action listener that can respond to menu commands
	 * in the menu that is created by the createJMenuBar() method.
	 */
	private class MenuHandler implements ActionListener {
		public void actionPerformed(ActionEvent evt) {
			String cmd = evt.getActionCommand();
			if (cmd.equals("Clear")) {
				ball = null;
				repaint();
			}
			else if (cmd.equals("Undo")) {
				// not yet implemented
			}
			else if (cmd.equals("Quit")) {
				int answer = JOptionPane.showConfirmDialog(display, 
				        "Do you really want to quit?", "Confirm Quit", 
				        JOptionPane.YES_NO_OPTION);
				if ( answer == JOptionPane.YES_OPTION)
					System.exit(0);
			}
		}
	}
	
	
	/**
	 * A class that defines an action listener that will respond to events
	 * from the time.  The actionPerformed method in this class moves the
	 * balls forwad by one time unit.
	 */
	private class TimerHandler implements ActionListener {
		public void actionPerformed(ActionEvent evt) {
			if (ball != null)
				ball.travel(1);
			display.repaint();
		}
	}
	
	
	/**
	 * Constructor.  Create all the components that are contained in this panel and 
	 * lay them out.  Start a timer to drive the animation.
	 */
	public BallPenPanel() {
		
		setBackground(Color.DARK_GRAY);
		setLayout(new BorderLayout(2,2));
		setBorder( BorderFactory.createLineBorder(Color.DARK_GRAY,2));

		display = new Display();
		this.add(display, BorderLayout.CENTER);
		
		JPanel bottom = new JPanel();
		bottom.setLayout(new GridLayout(1,6));
		bottom.setBackground(Color.LIGHT_GRAY);
		this.add(bottom, BorderLayout.SOUTH);
		
		colorChoice = new JComboBox();
		colorChoice.addItem("Red");
		colorChoice.addItem("Green");
		colorChoice.addItem("Blue");
		colorChoice.addItem("Cyan");
		colorChoice.addItem("Magenta");
		colorChoice.addItem("Yellow");
		colorChoice.addItem("Gray");
		colorChoice.addItem("Black");
		bottom.add(new JLabel("Color: ", JLabel.RIGHT));
		bottom.add(colorChoice);
		
		sizeChoice = new JComboBox();
		for (int i = 0; i < sizes.length; i++)
			sizeChoice.addItem("" + sizes[i] + " pixels");
		sizeChoice.setSelectedIndex(4);
		bottom.add(new JLabel("Size: ", JLabel.RIGHT));
		bottom.add(sizeChoice);
		
		speedChoice = new JComboBox();
		for (int i = 0; i < speeds.length; i++)
			speedChoice.addItem("" + (speeds[i]));
		speedChoice.setSelectedIndex(4);
		bottom.add(new JLabel("Speed: ", JLabel.RIGHT));
		bottom.add(speedChoice);
		
		Timer t = new Timer(30, new TimerHandler());
		t.start();
	}
	
	/**
	 * Create a menu bar that can be used with this panel, containing
	 * "Clear", "Undo", and "Quit" commands.
	 */
	public JMenuBar createMenuBar() {
		MenuHandler menuHandler = new MenuHandler();
		JMenu menu = new JMenu("Menu");
		JMenuItem clear = new JMenuItem("Clear");
		clear.addActionListener(menuHandler);
		clear.setAccelerator(KeyStroke.getKeyStroke("control X"));
		menu.add(clear);
		JMenuItem undo = new JMenuItem("Undo");
		undo.addActionListener(menuHandler);
		undo.setAccelerator(KeyStroke.getKeyStroke("control Z"));
		menu.add(undo);
		JMenuItem quit = new JMenuItem("Quit");
		quit.addActionListener(menuHandler);
		quit.setAccelerator(KeyStroke.getKeyStroke("control Q"));
		menu.add(quit);
		JMenuBar bar = new JMenuBar();
		bar.add(menu);
		return bar;
	}


}

