/* Livro Core Java 2 - Fundamentos */

/* Capítulo 8 - Manipulação de Eventos */

/* INTERFACES */

/* Exemplo: Que botão foi clicado? */

/* Eventos Semânticos  e Eventos de Baixo Nível no AWT - Abstract Windows Toolkit */

/* Eventos de Foco */

/* Evventos de Janela */

/* Eventos de Teclado */

/* 

A Listagem 8.3 mostra como lidar com teclas pressionadas.O programa é uma implementação
simples do brinquedo "Etch-A-Sketch", mostrado na Figura 8.7 do livro Core Java vol 1- pag 303, 
em que pode-se mover uma caneta pra cima, pra baixo, pra esquerda, pra direita.

Se for mantida pressionada a tecla SHIFT, então a caneta move-se com mais rapidez.Ou se vc 
estiver acostumado com o editor vi, poderá em vez de usar as teclas de movimento do cursor,
usar as teclas h,j, k, l para movimentar a caneta.
Neste caso, as letras H,J,K,L maiúsculas movem a caneta mais rapidamente.As teclas de movi-
mento são capturadas no método KeyPressed e os carcteres no método KeyTyped.

*/

/* importando pacotes */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class SketchPanel extends JPanel implements KeyListener
 {
	/* declarando um construtor */
	public SketchPanel()
	 {
		addKeyListener(this);
	 }//fim do construtor

	/* Método que informa qual tecla está sendo pressionada */
	/* Este método só funciona se a classe implementar a interface KeyListener*/
	public void KeyPressed(KeyEvent evt)
	 {
		//o método "int getKeyCode();" retorna o código virtual da tecla deste evento de tecla
		int KeyCode = evt.getKeyCode();
		int d;
		
		//fazendo um teste pra saber se a tecla shiftdown foi pressionada
		if(evt.isShiftDown())
			d=5;
		else
			d=1;

		if(KeyCode == KeyEvent.VK_LEFT) add(-d, 0); 
		else if(KeyCode == KeyEvent.VK_RIGHT) add(d, 0);
		else if(KeyCode == KeyEvent.VK_UP) add(0, -d);
		else if(KeyCode == KeyEvent.VK_DOWN) add(0, d);

	 }//fim do método KeyPressed
	
	/* Método que informa qual tecla está solta */
	/* Este método só funciona se a classe implementar a interface KeyListener*/
	public void KeyReleased(KeyEvent evt)
	 {}//fim do método KeyReleased
	
	/* Método que combina os dois métodos acima,  KeyPressed e KeyReleased */
	/* Este método informa os caracteres que foram gerados pelas teclas pressionadas pelo
	usuário */
	/* Este método só funciona se a classe implementar a interface KeyListener*/
	public void KeyTyped(KeyEvent evt)
	 {
		//o método getKeyChar() retorna o caracter que o usário digitou
		char KeyChar = evt.getKeyChar();
		int d;
		
		if(Character.isUpperCase(KeyChar))
		 {
			d=5;
			KeyChar = Character.toLowerCase(KeyChar);
		 }
		else
			d=1;
		if(KeyChar =='h') add(-d, 0);
		else if(KeyChar =='l') add(d, 0);
		else if(KeyChar =='k') add(0, -d);
		else if(KeyChar =='j') add(0, d);

	 }//fim do métod KeyTyped

	/* Há uma questão técnica:Normalmente, um painel não pode receber o foco do teclado, ou
	seja, ele não pode receber nehum evento de tecla pressionada.
	
	Para permitir que ele receba o foco, é necessário sobrepor o método isFocusTraversable da
	classe SketchPanel a fim de retornar true.
	
	Assim, quando o gerente de foco decidir que componente deve receber o foco, ele vai 
	encontrar exatamente um componente que está querendo aceitar o foco, que é o SketchPanel,
	e assim todos os eventos das teclas são enviados para esse painel.
	*/
	public boolean isFocusTraversable()
	 {
		return true;
	 }//fim do método isFocusTraversable
	
	public void add(int dx, int dy)
	 {
		end.x += dx;
		end.y += dy;

		Graphics g = getGraphics();
		g.drawLine(start.x, start.y, end.x, end.y);
		/* o método dispose() fecha a janela e recupera os recusros dos sistemas usados em
		sua criação */
		g.dispose();
		start.x = end.x;
		start.y = end.y;

	 }//fim do método add
	
	private Point start = new Point(0, 0);
	private Point end   = new Point(0, 0);

 }//fim da classe Sketch

class SketchFrame extends JFrame
 {//início da classe SketchFrame
	
	//declarando um construtor, aonde informo o título do Frame e o seu tamanho
	public SketchFrame()
	 {
		setTitle("Sketch");
		setSize(300, 200);
 
		/*método que finaliza o fechamento de um quadro(frame) ou seja encerramos o 
		programa de uma vez por todas.*/
		/* Infelizmente para implementar a interface WindowListener, uma classe precisa 
		implementar sete métodos.No nosso caso só precisaremos de um dos setes métodos 
		dessa classe, que seria o método "windowClosing(WindowEvent e)", responsável pela 
		saída do programa e desligamento da JVM - JAVA VIRTUAL MACHINE */
		addWindowListener(new WindowAdapter()
		 {
			public void windowClosing(WindowEvent e)
			 {
				System.exit(0);
			 }
		 });
	 
		Container contentPane = getContentPane();
		contentPane.add(new SketchPanel());

	 }//fim do construtor SketchFrame

 }//fim da classe SketchFrame

public class Sketch
 {
	 //método que torna a classe executável
	 public static void main(String args[])
	  {
		JFrame frame = new SketchFrame();
		frame.show();
	  }

 }//fim da classe Sketch
