import edu.neu.ccs.*;
import edu.neu.ccs.gui.*;
import edu.neu.ccs.codec.*;
import edu.neu.ccs.console.*;
import edu.neu.ccs.filter.*;
import edu.neu.ccs.jpf.*;
import edu.neu.ccs.parser.*;
import edu.neu.ccs.pedagogy.*;
import edu.neu.ccs.quick.*;
import edu.neu.ccs.util.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
import java.util.*;
import java.math.*;
import java.beans.*;
import java.lang.reflect.*;
import java.net.URL;
import java.util.regex.*;
import java.text.ParseException;

public class MultiKeyPlay
    extends DisplayPanel
    implements ConsoleAware
{
    public static int SIZE = 400;
    
    BufferedPanel window = new BufferedPanel(SIZE, SIZE);
    
    PaintableSequence sequence = window.getPaintableSequence();
    
    XRect shape = new XRect(100, 100, 50, 50);
    
    Paintable paintable = new ShapePaintable
        (shape, PaintMode.FILL, Colors.red);
    
    
    // JPT attaches the mouse and key adapters to an inner panel
    // that is obtained by the method call below
    //
    // The inner panel is needed to initialize and reset the key
    // listener
    DisplayPanel inner = window.getInnerPanel();
    
    
    // To activate listening for keys
    // one needs both the key adapter
    // which implements the KeyListener interface
    // and some additional initialization and reset code
    //
    // See the methods initializeKeys() and resetKeyFocus()
    KeyActionAdapter keyadapter = window.getKeyActionAdapter();
    
    
    // The key action object for key pressed events
    KeyAction keyPressedAction = new KeyAction() {
        public void keyActionPerformed(KeyEvent kevt) {
            handleKeyPress(kevt);
        }
    };
    
    
    // The key action object for key releaset events
    KeyAction keyReleasedAction = new KeyAction() {
        public void keyActionPerformed(KeyEvent kevt) {
            handleKeyRelease(kevt);
        }
    };
    
    
    // keep track of key states of interest to this program
    // ignore other keys
    
    boolean downPressed  = false;
    boolean upPressed    = false;
    boolean rightPressed = false;
    boolean leftPressed  = false;
    
    boolean shiftPressed = false;
    
    
    public MultiKeyPlay() {
        // initializations
        initializeWindow();
        initializeKeys();
        
        // instantiate GUI
        add(window);
        frame("Key Play");
        
        // set focus on the inner panel
        // after the GUI has been instantiated in its frame
        resetKeyFocus();
    }
    
    
    // The key action method for key pressed events
    void handleKeyPress(KeyEvent kevt) {
        switch(kevt.getKeyCode()) {
            case KeyEvent.VK_SHIFT:
                shiftPressed = true;
                break;
            
            case KeyEvent.VK_DOWN:
                downPressed = true;
                break;
            
            case KeyEvent.VK_UP:
                upPressed = true;
                break;
                
            case KeyEvent.VK_RIGHT:
                rightPressed = true;
                break;
                
            case KeyEvent.VK_LEFT:
                leftPressed = true;
                break;
                
            default:
                // if not a cursor key or the shift key
                // do nothing
                return;
        }
        
        updateScreen();
    }
    
    
    // The key action method for key released events
    void handleKeyRelease(KeyEvent kevt) {
        switch(kevt.getKeyCode()) {
            case KeyEvent.VK_SHIFT:
                shiftPressed = false;
                break;
            
            case KeyEvent.VK_DOWN:
                downPressed = false;
                break;
            
            case KeyEvent.VK_UP:
                upPressed = false;
                break;
                
            case KeyEvent.VK_RIGHT:
                rightPressed = false;
                break;
                
            case KeyEvent.VK_LEFT:
                leftPressed = false;
                break;
                
            default:
                // if not a cursor key or the shift key
                // do nothing
                return;
        }
        
        updateScreen();
    }
    
    
    void updateScreen() {
        // set delta to 10 if the shift key is down
        // otherwise set delta to 1
        int small = 1;
        int large = 10;
        
        int delta = (shiftPressed) ? large : small;
        
        // compute x, y shift
        int x = 0;
        int y = 0;
        
        if (rightPressed)
            x += delta;
        
        if (leftPressed)
            x -= delta;
        
        if (downPressed)
            y += delta;
        
        if (upPressed)
            y -= delta;
        
        if ((x != 0) || (y != 0)) {
            // move the paintable and repaint the window
            paintable.move(x, y);
            window.repaint();
        }
    }
    
    
    void initializeWindow() {
        window.drawGrid(50);
        sequence.addPaintable(paintable);
        
        window.repaint();
    }
    
    
    // The method to initialize key listening in the inner panel
    void initializeKeys() {
        // enable the inner panel to gain the focus of attention
        inner.setFocusable(true);
        
        // attach the pressed action object to the key adapter
        keyadapter.addKeyPressedAction(keyPressedAction);
        
        // attach the released action object to the key adapter
        keyadapter.addKeyReleasedAction(keyReleasedAction);
    }
    
    
    // The method to set or reset key listening to the inner panel
    void resetKeyFocus() {
        // reset the focus of attention to the inner panel
        // in case it has been set to some other component
        inner.requestFocusInWindow();
    }
    
    
    public static void main(String[] args) {
        new MultiKeyPlay();
    }
    
}
