// file: Sketch.java
// from Horstmann and Corneil's book

/**
 * The following demo is a "Etch-A-Sketch" toy where
 * you move a pen up, down, left, right with cursor keys
 * or h, j, k, l.  Holding down the SHIFT key at the same time
 * will move the pen by larger increments.
 *
 * The main purpose is the illustrate the use of KeyEvent and
 * the KeyListener interface.
 **/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class SketchPanel extends JPanel 
		  implements KeyListener {
  // members:
  private Point start = new Point(50, 50);
  private Point end = new Point(50, 50);
  static int INCREMENT = 3;

  // constructor:
  SketchPanel() {
    addKeyListener(this);
  }

  // methods:

  public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    int d;
    if (e.isShiftDown()) d = 5*INCREMENT;
    else d = INCREMENT;
    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);
  } // keyPressed

  public void keyReleased(KeyEvent e) {}

  public void keyTyped(KeyEvent e) {
    char keyChar = e.getKeyChar();
    int d;
    if (Character.isUpperCase(keyChar)) {
	d = 5*INCREMENT;
	keyChar = Character.toLowerCase(keyChar);
    } else d = INCREMENT;
    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);
  } // keyTyped

  // need to make the current panel "focusable" as the default
  //	for panels is not focusable.
  public boolean isFocusable() {return true;}
  	// NOTE: isFocusable() replaces the
	// deprecated method 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);
    g.dispose();  // COMMENT: we use Component.getGraphics() to 
		// draw immediately, rather than wait for the next call 
		// to paintComponent.  The g.dispose() method is needed
		// to release any graphics resources held by g.  In general,
		// you need to call dispose for any Graphics object that
		// you obtain yourself.  But not for the ones passed to you.
    start.x = end.x;
    start.y = end.y;
  } // add

  public void paint(Graphics g) {
    String instr = "INSTRUCTIONS: Type keys (h,j,k,l) or arrow keys to move";
    g.drawString(instr, 10, 10);
  }

} // Class SketchPanel

class Sketch extends JFrame {
  // constructor:
  public Sketch() {
    setTitle("Etch-a-Sketch");
    setSize(500, 300);
    addWindowListener(new WindowAdapter() {
	public void windowClosing(WindowEvent e) {
	  System.exit(0);
	}});
    Container contentPane = getContentPane();

    SketchPanel sp = new SketchPanel();
    contentPane.add(sp);
  } // Sketch constructor
  
  public static void main(String[] args) {
    JFrame frame = new Sketch();
    frame.show();
  } // main

}// Sketch Class

/**
 *  Exercise: allow a combination of 2 pressed keys to
 *  achieve diagonal directions.  E.g., 'h' + 'j' moves the pen
 *  in a South West direction.  See the book of Horstmann for hints.
 *  Exercise: have a blinking circle for current position
 **/

