package dessin;

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.border.*;
import java.awt.image.*;  
import java.util.ArrayList;

public class TestShape extends JPanel{
    private Color foregroundColor = Color.BLACK;

    private int l,h;
    private double a,b;


    // la courbe construite est stocke dans la variable gp.
    // C'est un objet de la classe GeneralPath qui permet faire les
    // courbes fermees ou ouvertes composees de segments de droite, 
    // segments quadratiques, segments cubiques.
    // gp contient uniquement les segments qui sont definitivement
    // termines

    // gpVolatile contient la même courbe que gp mais en plus
    // le dernier segment qui n'est pas termine tant que on n'a pas clique
    // sut le bouton 2 de a souris
    
    private GeneralPath gp;      // la partie terminee de la courbe courante
    private GeneralPath gpVolatile ; // courbe courante avec le dernier segment
                                     // volatile

    // indicateur true si on est en train de dessiner une courbe
    // false sinon
    private boolean pic;

    // la couleur courante
    private Color c = Color.BLACK;

    // ArrayList contenant toutes les courbes avec leurs couleurs
    private java.util.List<Objets> shapes=new ArrayList<Objets>();

    // class pour stocker les couples (shape,color) dans ArrayList shapes
    class Objets{
	Shape shape;
	Color color;
	Objets(Shape shape, Color color){
	    this.shape = shape;
	    this.color = color;
	}
	Shape getShape(){
	    return shape;
	}
	Color getColor(){
	    return color;
	}
    }


    public TestShape(int l, int h){
	this.l = l;
	this.h = h;

	setPreferredSize(new Dimension(l,h));
	setMaximumSize(new Dimension(l,h));
	setBackground(Color.WHITE);


	// la classe GeneralPath:
	// la methode GeneralPath.moveTo() 
	// nous deplace vers le sommet suivant de la courbe
	// la methode GeneralPath.lineTo()
	// nous deplace vers le sommet suivant
	// tout en dessinant le segment entre le sommet courant et
	// le sommet suivant
	addMouseListener(new MouseAdapter(){
		public void mousePressed(MouseEvent e){
		    a = e.getX(); b = e.getY();
		    //on commence a dessiner une courbe
		    if( !pic && e.getButton() == MouseEvent.BUTTON1 ){
			pic = true;
			gp = new GeneralPath();
			gp.moveTo(a,b);
			gpVolatile=(GeneralPath)gp.clone();
		    }// on ajoute un segment a la courbe courante
		    else if( pic && e.getButton() == MouseEvent.BUTTON1 ){
			gpVolatile=(GeneralPath)gp.clone();
			gpVolatile.lineTo(a,b);
			gp = (GeneralPath)gpVolatile.clone();
			repaint();
		    } // on termine la coure courante
		    else if( pic && e.getButton() == MouseEvent.BUTTON2 ){
			pic = false;

			// ajouter le couple (gp, c)
			// sur la liste de courbes terminees
			shapes.add(new Objets(gp, c));
			gpVolatile = gp;
			repaint();

		    }
		}
	    });
	
	//on ajoute le dernier segment dans la courbe volatile
	addMouseMotionListener(new  MouseMotionAdapter(){
		public void mouseMoved(MouseEvent e){
		    if(!pic)
			return;
		    a = e.getX();
		    b = e.getY();
		    gpVolatile=(GeneralPath)gp.clone();
		    gpVolatile.lineTo(a,b);
		    repaint(); //never call paint()
		}
	    });


    }// fin de constructeur
    

    // methode appeler chaque fois quand on redessine le tableau
    // contenant le dessin
    protected void paintComponent(Graphics g){
	super.paintComponent(g);
	Graphics2D g2 = (Graphics2D)g;	

	// dessiner toutes les corbes precedentes
	// sauvegardees dans ArrayList de shapes
	int n = shapes.size();
	for(int i=0; i < n ; i++){
	    Objets o = shapes.get(i);
	    g2.setColor(o.getColor());
	    g2.draw(o.getShape());
	}
	// revenir a la couleur courante
	// dessiner la derniere courbe non achevee
	g.setColor(c);
	if(gpVolatile == null)
	    return;
	// s'il existe une courbe non terminee dans gpVolatile
	// alors la dessiner aussi
	g2.draw(gpVolatile);
    }

    private static void createGUI(){
	final TestShape table = new TestShape(500,500);

	JPanel ext = new JPanel();
	ext.setBorder(BorderFactory.createCompoundBorder(
		        BorderFactory.createEmptyBorder(10,10,10,10), 
	                BorderFactory.createBevelBorder(BevelBorder.RAISED))
		      );
	ext.setLayout(new BorderLayout());
	ext.add(table,BorderLayout.CENTER);
	ext.setMaximumSize(ext.getPreferredSize());

	Box box = Box.createHorizontalBox();
	box.add(Box.createHorizontalGlue());
	box.add(ext);
	box.add(Box.createHorizontalGlue());

	final JFrame frame = new JFrame();
	frame.setContentPane(box);

	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	/**************************************************************
	 * construire JMenuBar
	 *************************************************************/

	JMenuBar bar = new JMenuBar();
	JMenu menu = new JMenu("File");
	JMenuItem mi = new JMenuItem("Quit");
	mi.setMnemonic(KeyEvent.VK_Q);
	mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,InputEvent.CTRL_DOWN_MASK));
	mi.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e){
		    System.exit(0);
		}
	    });
	menu.add(mi);
	bar.add(menu);
	menu = new JMenu("Tools");
	mi= new JMenuItem("Foreground Color");
	mi.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e){
		    Color c = JColorChooser.showDialog(frame,
			 "Choose foreground color", 
			  table.getForeground());
		    if( c != null )
			table.c = c;
		}});
		
	menu.add(mi);
	bar.add(menu);
	frame.setJMenuBar(bar);

	frame.pack();//frame.show();
	frame.setVisible(true);
    }

    public static void main(String[] args){
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createGUI();
            }
        });
    }
}



