import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;


/**
*<strong> Clase que implementa un entorno para el dibujo y la manipulacion de
* Figuras Geométricas.<strong>
*/
public class Dibujo extends JPanel
{

/**
*ArrayList que contiene todas las Figuras Geométricas que se dibujan en Dibujo.
*/
 private ArrayList formas;
/**
* MouseListener que se usa para responder a los eventos del Mouse en Dibujo.
*/
 private MouseListener currentMouseListener;
 
/**
* MouseMotionListener que se usa para responder a los movimientos del Mouse en Dibujo.
*/
 private MouseMotionListener currentMouseMotionListener;
 
/**
* Permite saber si hay una figura seleccionada en Dibujo. Si una figura está
* seleccionada, selección = el index de la Figura en el ArrayList formas,
* sino selección = -1.
*/
 private int seleccion = -1;
 
/**
* Construye un Dibujo para el dibujo de formas geométricas, con sus Listeners
* asociados.
*/
 public  Dibujo()
{
super();
setBackground(Color.white);
formas = new ArrayList();
currentMouseListener = null;
currentMouseMotionListener = null;
addMouseListener(currentMouseListener);
addMouseMotionListener(currentMouseMotionListener);
}

/**
* Cambia el MouseListener asociado a Dibujo por el MouseListener dado en
* parametro. 
* @param l Nuevo MouseListener asociado a Dibujo.
*/
public void changeMouseListener(MouseListener l)
{
if (currentMouseListener != null)
     removeMouseListener(currentMouseListener);
currentMouseListener = l;
addMouseListener(currentMouseListener);
}

/**
* Cambia el MouseMotionListener asociado a Dibujo por el MouseMotionListener
* dado en parametro. 
* @param l Nuevo MouseMotionListener asociado a Dibujo.
*/  
public void changeMouseMotionListener(MouseMotionListener l)
{
if (currentMouseMotionListener != null)
    removeMouseMotionListener(currentMouseMotionListener);
currentMouseMotionListener = l;
addMouseMotionListener(currentMouseMotionListener);
}

/**
* Dibuja todas las figuras del ArrayList formas en Dibujo.
* @param g Graphics usado para dibujar las formas.
*/
public void paintComponent(Graphics g) 
{ 
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// Si una figura está seleccionada, se dibujan cuadraditos verdes
// a cada una de sus esquinas para visualisar la selección.
if (seleccion != -1)((Forma)formas.get(seleccion)).select(g);

for (int i = 0; i < formas.size(); i++)
((Forma)formas.get(i)).paintComponent(g2d);
}

/** Escala la forma seleccionada respecto al punto central en un factor dado.
* @param centro Punto respecto del cual se hace el escalamiento.
* @param factor Factor usado en el escalamiento. >1 corresponde 
* a amplificación, <1 corresponde a reducción.
*/
public void escalar (Point centro, double factor) 
{
if (seleccion != -1)
((Forma)formas.get(seleccion)).escalar(centro, factor);
repaint();
}
/** Traslada la forma seleccionada desplazandola en sentido X e Y.
* @param deltaX desplazamiento en sentido horizontal.
* @param deltaY desplazamiento en sentido vertical.
*/
public void trasladar (double deltaX, double deltaY) 
{
if (seleccion != -1)
((Forma)formas.get(seleccion)).trasladar(deltaX, deltaY);
repaint();
}
/** Rota la forma seleccionada respecto al punto central en un ángulo dado.
* @param centro Punto respecto del cual se hace la rotación.
* @param deltaAngulo ángulo de rotación en radianes.
*/ 
public void rotar (Point centro, double deltaAngulo) 
{
if (seleccion != -1)
   {
   ((Forma)formas.get(seleccion)).rotar(centro, deltaAngulo);
   repaint();
   }
}

/**
* Permite saber si una figura de Dibujo esta seleccionada, es decir si el
* punto dado en parametro pertenece a una figura del ArrayList formas.
* @param p Punto cuyas coordinadas estan revisadas para saber si pertenece
* a una figura del ArrayList formas.
* @return True si el punto pertenece a una figura, False sino.
*/
public boolean isAComponentSelected(Point p)
{
for (int i = 0; i < formas.size(); i++)
   {
   if (((Forma)formas.get(i)).isSelected(p))
      {
       seleccion = i;
       repaint();
       return true;
      }
   }
repaint();
seleccion = -1;
return false;
} 

/**
* Permite saber si el punto dado en parametro está adentro de uno de los
* cuadraditos verdes de la figura seleccionada.
* @param p Punto cuyas coordinadas estan revisadas para saber si está
* adentro de uno de los cuadraditos verdes de la figura seleccionada.
* @return True si el punto pertenece a un cuadradito verde, False sino.
*/
public boolean isItInAGreenSquare (Point p)
{
if (seleccion != -1)
   return (((Forma)formas.get(seleccion)).isItInAGreenSquare(p));
else return false;
}

/**
* Remueva la forma dada en parametro del ArrayList formas.
* @param f Forma que se quitta del ArrayList formas.
*/ 
public void remueva (Forma f)
{
formas.remove(f);
repaint();
}

/**
* Incorpora la forma dada en parametro al ArrayList formas.
* @param f Forma que se incorpora al ArrayList formas.
*/
public void incorpore (Forma f)
{
formas.add(f);
repaint();
}  

}




