Proyecto_1.java



//	__________________________________________________________________________________________________________
//	OBJETIVOS:	Se crea una ventana con menUs y nos permite dibujar N Objetos
//			Los objetos son:
//					Lineas, Circulos, Cuadros, Cubos, Conos, Cilindros
//
//	       LINEA	2 CLICKS
//	     CIRCULO	2 CLICKS
//	      ELIPSE	2 CLICKS
//	      CUADRO	2 CLICKS
//		CUBO	4 CLICKS
//			Para ello, en el cubo se dan 4 clicks -2 para un cuadro y 2 para un
//			segundo cuadro uniendose los vErtices con lIneas para formar al cubo
//					P1 ( sup-izq, inf-der )
//		CONO	3 CLICKS
//			Son necesarios 3 clicks. 2 para la base -elipse- y uno para el vErtice
//			________________________________________________________________________________
//			OJO <<<< Los 2 primeros clicks son para la elipse y el click 3 para el pico >>>>
//			--------------------------------------------------------------------------------
//	    CILINDRO	4 CLICKS
//			Se utilizan 4 clicks, 2 para la base -elipse-, 2 para la parte
//			superior -elipse- y se unen automAticamente con 2 lIneas.
//
//	PARTICULARIDADES
//			1.- Al hacer cambio de primitiva, N_CLICKS se pone a cero.
//
//			2.- AUn cuando algunos objetos aparentan tener volUmen, se trabajan como
//			figuras planas. Es 2D, NO HAY TRAZOS 3D
//
//			3.- Se hace uso de la clase LinkedList que viene con el jdk para el
//			el manejo de listas ligadas.
//	__________________________________________________________________________________________________________

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

public class Proyecto_1 extends JFrame
{
	JMenu MenuArchivo, MenuGrafico, MenuEdicion, MenuColores;
	JMenuItem ArchivoGuardar, ArchivoSalir, GraficoLinea, GraficoCirculo, EdicionLimpiar;
	JMenuItem ColorAzul, ColorAmarillo, ColorBlanco, ColorVerde;
	JMenuItem GraficoElipse, GraficoCuadro, GraficoCubo, GraficoCono, GraficoCilindro;
	Grafico G = new Grafico();
	
	final int NADA = 0, LINEA = 1, CIRCULO = 2, ELIPSE = 3, CUADRO = 4, CUBO = 5, CONO = 6, CILINDRO = 7;
	final int AZUL = 1, AMARILLO = 2, BLANCO = 3, VERDE = 4;
	int X[] = new int[4], Y[] = new int[4];
	int N_CLICKS = 0, Primitiva = NADA, color = AMARILLO;

	public static void main(String R[]) { new Proyecto_1(); }

	public Proyecto_1()
	{
		this.getContentPane().setLayout(null);		// Contenedor nulo
		this.setTitle("Editor Grafico 1.0");		// Titulo de la ventana
		this.setResizable(true);			// Si es redimensionable
		this.setLocation(100, 100);			// Posicion
		this.setSize(new Dimension(700, 500));		// Dimensiones
		this.setBackground(Color.green);
		this.add(G); G.setBounds(0, 0, 700, 500);

		JMenuBar BarraMenu = new JMenuBar();		// Barra de menU
		BarraMenu.setBackground(Color.green);
		BarraMenu.setForeground(Color.yellow);
			MenuArchivo = InsertaMenu("Archivo");
			MenuArchivo.setMnemonic(KeyEvent.VK_A);		// Se accesa con Alt-A
			InsertaItem(MenuArchivo, ArchivoGuardar, "guardaR", KeyEvent.VK_R);	//Alt-R
			InsertaItem(MenuArchivo, ArchivoSalir, "Salir", KeyEvent.VK_S);	//Alt-S

			MenuGrafico = InsertaMenu("Primitiva");
			MenuGrafico.setMnemonic(KeyEvent.VK_P);			// Se accesa con Alt-G
			InsertaItem(MenuGrafico, GraficoLinea, "Linea", KeyEvent.VK_L);		// Alt-L
			InsertaItem(MenuGrafico, GraficoCirculo, "Circulo", KeyEvent.VK_I);	// Alt-I
			InsertaItem(MenuGrafico, GraficoElipse, "Elipse", KeyEvent.VK_E);	// Alt-E
			InsertaItem(MenuGrafico, GraficoCuadro, "Cuadro", KeyEvent.VK_U);
			InsertaItem(MenuGrafico, GraficoCubo, "Cubo", KeyEvent.VK_B);
			InsertaItem(MenuGrafico, GraficoCono, "Cono", KeyEvent.VK_N);
			InsertaItem(MenuGrafico, GraficoCilindro, "Cilindro", KeyEvent.VK_D);

			MenuEdicion = InsertaMenu("Edicion");
			MenuEdicion.setMnemonic(KeyEvent.VK_E);			// Se accesa con Alt-E
			InsertaItem(MenuEdicion, EdicionLimpiar, "Limpiar", KeyEvent.VK_L);	// Alt-L

			MenuColores = InsertaMenu("Color");
			InsertaItem(MenuColores, ColorAzul, "Azul", KeyEvent.VK_A);
			InsertaItem(MenuColores, ColorAmarillo, "Amarillo", KeyEvent.VK_M);
			InsertaItem(MenuColores, ColorBlanco, "Blanco", KeyEvent.VK_B);
			InsertaItem(MenuColores, ColorVerde, "Verde", KeyEvent.VK_V);
	
			BarraMenu.add(MenuArchivo);
			BarraMenu.add(MenuGrafico);
			BarraMenu.add(MenuEdicion);
			BarraMenu.add(MenuColores);
		setJMenuBar(BarraMenu);
		G.addMouseListener(new EventoRaton());

		this.setVisible(true);
	}

	JMenu InsertaMenu(String CAD) { return new JMenu(CAD); }

	void InsertaItem(JMenu MENU, JMenuItem ITEM, String CAD, int KEY_EVENT)
	{
		ITEM = new JMenuItem(CAD);
		ITEM.setMnemonic(KEY_EVENT);
		ITEM.setBackground(Color.green);
		ITEM.setForeground(Color.black);
		MENU.add(ITEM);
		ITEM.addActionListener(new Evento_Opciones());
	}

	protected void processWindowEvent(WindowEvent e)
	{ if (e.getID() == WindowEvent.WINDOW_CLOSING) System.exit(0); }

	class Evento_Opciones implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			if (e.getActionCommand().equals("Salir")) System.exit(0);
			if (e.getActionCommand().equals("Guardar")) { }
			if (e.getActionCommand().equals("Limpiar")) { G.LimpiaVentana( ); }

			if (e.getActionCommand().equals("Linea"))	{ Primitiva = LINEA; N_CLICKS = 0; }
			if (e.getActionCommand().equals("Circulo"))	{ Primitiva = CIRCULO; N_CLICKS = 0; }
			if (e.getActionCommand().equals("Elipse"))	{ Primitiva = ELIPSE; N_CLICKS = 0; }
			if (e.getActionCommand().equals("Cuadro"))	{ Primitiva = CUADRO; N_CLICKS = 0; }
			if (e.getActionCommand().equals("Cubo"))	{ Primitiva = CUBO; N_CLICKS = 0; }
			if (e.getActionCommand().equals("Cono"))	{ Primitiva = CONO; N_CLICKS = 0; }
			if (e.getActionCommand().equals("Cilindro"))	{ Primitiva = CILINDRO; N_CLICKS = 0; }

			if (e.getActionCommand().equals("Azul"))	color = AZUL;
			if (e.getActionCommand().equals("Amarillo"))	color = AMARILLO;
			if (e.getActionCommand().equals("Blanco"))	color = BLANCO;
			if (e.getActionCommand().equals("Verde"))	color = VERDE;
		}
	}
	
	class EventoRaton implements MouseListener
	{
		// Estos mEtodos no nos interesan por ahora. Sin embargo hay que ponerlos
		// al tratarse de una interfaz
		public void mouseEntered(MouseEvent e) {}
		public void mouseExited(MouseEvent e) {}
		public void mousePressed(MouseEvent e) {}
		public void mouseReleased(MouseEvent e) {}
		// Se crea el mEtodo que si nos interesa trabajar
		public void mouseClicked(MouseEvent e)
		{
			String boton = "";
			if ( Primitiva != NADA )
			{
				X[N_CLICKS] = e.getX();
				Y[N_CLICKS] = e.getY();
				N_CLICKS++;
			}
			
			switch (e.getButton())
			{
				// boton = "izquierdo";
				case MouseEvent.BUTTON1:
					if ( ( N_CLICKS == 2 ) &&
						( (Primitiva == LINEA) || (Primitiva == CIRCULO) || (Primitiva == ELIPSE) || (Primitiva == CUADRO) )
					   )	{ G.Dibuja(X, Y, Primitiva, color); N_CLICKS = 0; }
					if ( ( N_CLICKS == 3 ) && (Primitiva == CONO) )
						{ G.Dibuja(X, Y, Primitiva, color); N_CLICKS = 0; }
					if ( ( N_CLICKS == 4 ) && ( (Primitiva == CUBO) || (Primitiva == CILINDRO) ) )
						{ G.Dibuja(X, Y, Primitiva, color); N_CLICKS = 0; }
					break;
				case MouseEvent.BUTTON2: break;		// boton = "central";
				case MouseEvent.BUTTON3: break;		// boton = "derecho";
			}
		}
	}
}

class Grafico extends Canvas
{
	final int NADA = 0, LINEA = 1, CIRCULO = 2, ELIPSE = 3, CUADRO = 4, CUBO = 5, CONO = 6, CILINDRO = 7;
	final int AZUL = 1, AMARILLO = 2, BLANCO = 3, VERDE = 4;
        int Primitiva = NADA, color = NADA;
	boolean Limpiar = false;

	LinkedList L_Lineas	= new LinkedList();
	LinkedList L_Circulos	= new LinkedList();
	LinkedList L_Elipses	= new LinkedList();
	LinkedList L_Cuadros	= new LinkedList();
	LinkedList L_Cubos	= new LinkedList();
	LinkedList L_Conos	= new LinkedList();
	LinkedList L_Cilindros	= new LinkedList();


	public Grafico()
	{
		setBackground(Color.red);		// Color del fondo
		setForeground(Color.yellow);		// Color de los trazos
		LimpiaVentana( );
	}

	void Dibuja(int X[], int Y[], int Primitiva, int color)
	{
		Color Tinta = Color.red;

		if ( color == AZUL )		Tinta = Color.blue;
		if ( color == AMARILLO )	Tinta = Color.yellow;
		if ( color == BLANCO )		Tinta = Color.white;
		if ( color == VERDE )		Tinta = Color.green;

		switch ( Primitiva )
		{
			case LINEA:	L_Lineas.add( new Linea(Tinta, X, Y) );		break;
			case CIRCULO:	L_Circulos.add( new Circulo(Tinta, X, Y ) );	break;
			case ELIPSE:	L_Elipses.add( new Cuadro(Tinta, X, Y ) );	break;
			case CUADRO:	L_Cuadros.add( new Cuadro(Tinta, X, Y ) );	break;
			case CUBO:	L_Cubos.add( new Cubo(Tinta, X, Y) );		break;
			case CONO:	L_Conos.add( new Cono(Tinta, X, Y) );		break;
			case CILINDRO:	L_Cilindros.add( new Cilindro(Tinta, X, Y) );	break;
		}
		repaint();
	}

	void Dibuja_Linea(Graphics A, Color color, int x1, int y1, int x2, int y2)
	{ A.setColor(color); A.drawLine(x1, y1, x2, y2); }

	void Dibuja_Cuadro(Graphics A, Color color, int x, int y, int ancho, int alto)
	{ A.setColor(color); A.drawRect(x, y, ancho, alto); }

	void Dibuja_Elipse(Graphics A, Color color, int x, int y, int ancho, int alto)
	{ A.setColor(color); A.drawOval(x, y, ancho, alto); }

	public void paint(Graphics A)
	{
		Linea L_Actual; Circulo C_Actual; Cuadro Cu_Actual; Cubo Cb_Actual; Cono Co_Actual; Cilindro Ci_Actual;

		int x = 0;

		if ( !Limpiar )
		{
			// L I N E A S
			// ___________________

			for ( x = 0; x < L_Lineas.size(); x++)
			{
				L_Actual = (Linea)L_Lineas.get(x);
				Dibuja_Linea(A, L_Actual.color, L_Actual.V1.X, L_Actual.V1.Y, L_Actual.V2.X, L_Actual.V2.Y );
			}
			// C I R C U L O S
			// ___________________
			for ( x = 0; x < L_Circulos.size(); x++)
			{
				C_Actual = (Circulo)L_Circulos.get(x);
				A.setColor( C_Actual.color );
				A.drawOval( C_Actual.X, C_Actual.Y, C_Actual.Diametro, C_Actual.Diametro );
			}
			// E L I P S E S
			// ___________________
			for ( x = 0; x < L_Elipses.size(); x++)
			{
				Cu_Actual = (Cuadro)L_Elipses.get(x);
				Dibuja_Elipse(A, Cu_Actual.color, Cu_Actual.X, Cu_Actual.Y, Cu_Actual.Ancho, Cu_Actual.Alto );
			}
			// C U A D R O S
			// ___________________
			for ( x = 0; x < L_Cuadros.size(); x++)
			{
				Cu_Actual = (Cuadro)L_Cuadros.get(x);
				Dibuja_Cuadro(A, Cu_Actual.color, Cu_Actual.X, Cu_Actual.Y, Cu_Actual.Ancho, Cu_Actual.Alto );
			}
			// C U B O S
			// ___________________
			for ( x = 0; x < L_Cubos.size(); x++)
			{
				Cb_Actual = (Cubo)L_Cubos.get(x);
				Dibuja_Cuadro(A, Cb_Actual.C1.color, Cb_Actual.C1.X, Cb_Actual.C1.Y, Cb_Actual.C1.Ancho, Cb_Actual.C1.Alto);
				Dibuja_Cuadro(A, Cb_Actual.C2.color, Cb_Actual.C2.X, Cb_Actual.C2.Y, Cb_Actual.C2.Ancho, Cb_Actual.C2.Alto);
				Dibuja_Linea( A, Cb_Actual.L1.color, Cb_Actual.L1.V1.X, Cb_Actual.L1.V1.Y, Cb_Actual.L1.V2.X, Cb_Actual.L1.V2.Y);
				Dibuja_Linea( A, Cb_Actual.L2.color, Cb_Actual.L2.V1.X, Cb_Actual.L2.V1.Y, Cb_Actual.L2.V2.X, Cb_Actual.L2.V2.Y);
				Dibuja_Linea( A, Cb_Actual.L3.color, Cb_Actual.L3.V1.X, Cb_Actual.L3.V1.Y, Cb_Actual.L3.V2.X, Cb_Actual.L3.V2.Y);
				Dibuja_Linea( A, Cb_Actual.L4.color, Cb_Actual.L4.V1.X, Cb_Actual.L4.V1.Y, Cb_Actual.L4.V2.X, Cb_Actual.L4.V2.Y);
			}
			// C O N O S
			// ___________________
			for ( x = 0; x < L_Conos.size(); x++)
			{
				Co_Actual = (Cono)L_Conos.get(x);
				Dibuja_Elipse(A, Co_Actual.C.color, Co_Actual.C.X, Co_Actual.C.Y, Co_Actual.C.Ancho, Co_Actual.C.Alto);

				Dibuja_Linea( A, Co_Actual.L1.color, Co_Actual.L1.V1.X, Co_Actual.L1.V1.Y, Co_Actual.L1.V2.X, Co_Actual.L1.V2.Y);
				Dibuja_Linea( A, Co_Actual.L2.color, Co_Actual.L2.V1.X, Co_Actual.L2.V1.Y, Co_Actual.L2.V2.X, Co_Actual.L2.V2.Y);
			}
			// C I L I N D R O S
			// ___________________
			for ( x = 0; x < L_Cilindros.size(); x++)
			{
				Ci_Actual = (Cilindro)L_Cilindros.get(x);
				Dibuja_Elipse(A, Ci_Actual.C1.color, Ci_Actual.C1.X, Ci_Actual.C1.Y, Ci_Actual.C1.Ancho, Ci_Actual.C1.Alto);
				Dibuja_Elipse(A, Ci_Actual.C2.color, Ci_Actual.C2.X, Ci_Actual.C2.Y, Ci_Actual.C2.Ancho, Ci_Actual.C2.Alto);

				Dibuja_Linea( A, Ci_Actual.L1.color, Ci_Actual.L1.V1.X, Ci_Actual.L1.V1.Y, Ci_Actual.L1.V2.X, Ci_Actual.L1.V2.Y);
				Dibuja_Linea( A, Ci_Actual.L2.color, Ci_Actual.L2.V1.X, Ci_Actual.L2.V1.Y, Ci_Actual.L2.V2.X, Ci_Actual.L2.V2.Y);
			}
		}
		else Limpiar = false;
	}

	void LimpiaVentana( )
	{
		L_Lineas.clear();	L_Circulos.clear();	L_Elipses.clear();	L_Cuadros.clear();
		L_Cubos.clear();	L_Conos.clear();	L_Cilindros.clear();
		Limpiar = true;
		repaint();
	}
}

class Vertice
{
	int X = 0, Y = 0;
	public Vertice() {}
	public Vertice(int X, int Y) { this.X = X; this.Y = Y; }
}

class Linea
{
	Vertice V1 = new Vertice();
	Vertice V2 = new Vertice();
	Color color = Color.white;

	public Linea() { }		// Se quedan los datos en ceros
	public Linea(Color color, int X[], int Y[])
	{
		V1.X = X[0]; V1.Y = Y[0];
		V2.X = X[1]; V2.Y = Y[1];
		this.color = color;
	}
}

class Circulo
{
	int X = 0, Y = 0, Radio = 0, Diametro = 0;
	Color color = Color.white;

	public Circulo() {}		// Se quedan los datos en ceros
	public Circulo(Color color, int Xs[], int Ys[])
	{
		Radio = (int) Math.hypot ( (double)(Xs[1] - Xs[0]), (double)(Ys[1] - Ys[0]) );
		X = Xs[0] - Radio;
		Y = Ys[0] - Radio;
		Diametro = 2 * Radio;
		this.color = color;
	}
}

//______________________________________________________________________________
// Se use la misma clase para el CUADRO que para la ELIPSE ya que son datos
//                               ------             ------
// y comportamientos exActamente iguales.
// La diferencia estA en el comando de dibujo, sin embargo se guardan
// en lista diferentes para su control correcto
//------------------------------------------------------------------------------
class Cuadro
{
	int X = 0, Y = 0, Ancho = 0, Alto = 0;
	Color color = Color.white;

	public Cuadro() {}		// Se quedan los datos en ceros
	public Cuadro(Color color, int Xs[], int Ys[])
	{
		Ancho = (Xs[0] > Xs[1]) ? (Xs[0] - Xs[1]) : (Xs[1] - Xs[0]);	// ( mayor - menor )
		Alto  = (Ys[0] > Ys[1]) ? (Ys[0] - Ys[1]) : (Ys[1] - Ys[0]);	// ( mayor - menor )
		X = (Xs[0] < Xs[1]) ? Xs[0] : Xs[1];				// La menor de las x's
		Y = (Ys[0] < Ys[1]) ? Ys[0] : Ys[1];				// La menor de las y's
		this.color = color;
	}
}

class Cubo
{
	Cuadro C1 = new Cuadro( );		Cuadro C2 = new Cuadro( );
	Linea L1 = new Linea( );		Linea L2 = new Linea( );
	Linea L3 = new Linea( );		Linea L4 = new Linea( );
	int X[] = new int[2], Y[] = new int[2];

	Color color = Color.white;

	public Cubo() {}		// Datos iniciales en 0's
	public Cubo(Color color, int Xs[], int Ys[])
	{
		this.color = color;
		// Cuadros base
		X[0] = Xs[0]; X[1] = Xs[1]; Y[0] = Ys[0]; Y[1] = Ys[1];
		C1 = new Cuadro(color, X, Y);
		X[0] = Xs[2]; X[1] = Xs[3]; Y[0] = Ys[2]; Y[1] = Ys[3];
		C2 = new Cuadro(color, X, Y);

		// LIneas complementarias
		X[0] = C1.X; X[1] = C2.X; Y[0] = C1.Y; Y[1] = C2.Y;
		L1 = new Linea(color, X, Y);		// superior izquierda

		X[0] = C1.X+C1.Ancho; X[1] = C2.X+C2.Ancho; Y[0] = C1.Y; Y[1] = C2.Y;
		L2 = new Linea(color, X, Y);		// superior derecha

		X[0] = C1.X; X[1] = C2.X; Y[0] = C1.Y+C1.Alto; Y[1] = C2.Y+C2.Alto;
		L3 = new Linea(color, X, Y);		// inferior izquierda

		X[0] = C1.X+C1.Ancho; X[1] = C2.X+C2.Ancho; Y[0] = C1.Y+C1.Alto; Y[1] = C2.Y+C2.Alto;
		L4 = new Linea(color, X, Y);		// inferior derecha
	}
}

class Cono
{
	Linea L1 = new Linea();		Linea L2 = new Linea();
	Cuadro C = new Cuadro();		// para la elipse
	int X[] = new int[2], Y[] = new int[2];
	Color color = Color.white;

	public Cono() {}		// Datos iniciales en 0's
	public Cono(Color color, int Xs[], int Ys[])
	{
		this.color = color;
		X[0] = Xs[0]; X[1] = Xs[1]; Y[0] = Ys[0]; Y[1] = Ys[1];
		C = new Cuadro(color, X, Y);

		if (C.Ancho > C.Alto)			// Es un cono vertical <<<<<<<<<<<
		{
			X[0] = C.X; X[1] = Xs[2]; Y[0] = C.Y+C.Alto/2; Y[1] = Ys[2];
			L1 = new Linea(color, X, Y);

			X[0] = C.X+C.Ancho; X[1] = Xs[2]; Y[0] = C.Y+C.Alto/2; Y[1] = Ys[2];
			L2 = new Linea(color, X, Y);
		}
		else					// Es un cono horizontal <<<<<<<<<<<
		{
			X[0] = C.X+C.Ancho/2; X[1] = Xs[2]; Y[0] = C.Y; Y[1] = Ys[2];
			L1 = new Linea(color, X, Y);

			X[0] = C.X+C.Ancho/2; X[1] = Xs[2]; Y[0] = C.Y+C.Alto; Y[1] = Ys[2];
			L2 = new Linea(color, X, Y);
		}
	}	
}

class Cilindro
{
	Cuadro C1 = new Cuadro(), C2 = new Cuadro();			// Las 2 elipses
	Linea L1 = new Linea(), L2 = new Linea();
	int X[] = new int[2], Y[] = new int[2];
	Color color = Color.white;

	public Cilindro() {}		// Datos iniciales en 0's
	public Cilindro(Color color, int Xs[], int Ys[])
	{
		this.color = color;
		X[0] = Xs[0]; X[1] = Xs[1]; Y[0] = Ys[0]; Y[1] = Ys[1];
		C1 = new Cuadro(color, X, Y);

		X[0] = Xs[2]; X[1] = Xs[3]; Y[0] = Ys[2]; Y[1] = Ys[3];
		C2 = new Cuadro(color, X, Y);

		if (C1.Ancho > C1.Alto)			// Es un cilindro vertical <<<<<<<<<<<
		{
			X[0] = C1.X; X[1] = C2.X; Y[0] = C1.Y+C1.Alto/2; Y[1] = C2.Y+C2.Alto/2;
			L1 = new Linea(color, X, Y);

			X[0] = C1.X+C1.Ancho; X[1] = C2.X+C2.Ancho; Y[0] = C1.Y+C1.Alto/2; Y[1] = C2.Y+C2.Alto/2;
			L2 = new Linea(color, X, Y);
		}
		else					// Es un cilindro horizontal <<<<<<<<<<<
		{
			X[0] = C1.X+C1.Ancho/2; X[1] = C2.X+C2.Ancho/2; Y[0] = C1.Y; Y[1] = C2.Y;
			L1 = new Linea(color, X, Y);

			X[0] = C1.X+C1.Ancho/2; X[1] = C2.X+C2.Ancho/2; Y[0] = C1.Y+C1.Alto; Y[1] = C2.Y+C2.Alto;
			L2 = new Linea(color, X, Y);
		}
	}
}