/* @(#)PaintableCanvas.java  */
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.*;
import java.util.regex.*;

// import java.text.*;

public class PaintableCanvas
    extends JComponent
    implements JPTConstants, ConsoleAware
{
    private PaintableSequence sequence =
        new PaintableSequence();
    
    private MouseActionAdapter mouseadapter =
        new MouseActionAdapter(this);
    
    private int oldX;   // old mouse X position in drag operation
    
    private int oldY;   // old mouse Y position in drag operation
    
    private int newX;   // new mouse X position in drag operation
    
    private int newY;   // new mouse Y position in drag operation
    
    private boolean dragging = false;    // are we dragging?
    
    private MutatablePaintable movable;  // what we are dragging
    
    
    private MouseAction mousePressedAction =
        new MouseAction() {
            public void mouseActionPerformed(MouseEvent evt) {
                mousePressed(evt);
            }
    };
        
    private MouseAction mouseDraggedAction =
        new MouseAction() {
            public void mouseActionPerformed(MouseEvent evt) {
                mouseDragged(evt);
            }
    };
      
    
    public PaintableCanvas(int width, int height) {
        setPreferredSize(new Dimension(width, height));
        setBackground(Color.white);
        installMouseActions();
    }
    
    
    public PaintableSequence getPaintableSequence() {
        return sequence;
    }
    
    
    public MouseActionAdapter getMouseActionAdapter() {
        return mouseadapter;
    }
    
    
    protected void paintComponent(Graphics g) {
        // paint background first
        // for simplicity assumes no border
        Color bg = getBackground();
        
        if (bg != null) {
            Dimension dimension = getPreferredSize();
            
            int w = dimension.width;
            int h = dimension.height;
            
            Rectangle2D bounds =
                new Rectangle2D.Double(0, 0, w, h);
            
            Graphics2D g2 = (Graphics2D) g;
            
            g2.setPaint(bg);
            g2.fill(bounds);
        }
        
        // paint sequence on top of background
        sequence.paint(g);
    }
    
    
    private void installMouseActions() {
        mouseadapter.addMousePressedAction(mousePressedAction);
        mouseadapter.addMouseDraggedAction(mouseDraggedAction);
    }
    
    
    private void mousePressed(MouseEvent evt)
    {
        oldX = evt.getX();
        oldY = evt.getY();
        
        movable = sequence.hits(oldX, oldY);
        
        dragging = movable != null;
        
        if (dragging) {
            sequence.shiftPaintableToTop(movable);
            repaint();
        }
     }
    
    
    private void mouseDragged(MouseEvent evt)
    {
        if (dragging) {
            newX = evt.getX();
            newY = evt.getY();
            
            movable.move(newX - oldX, newY - oldY);
            
            oldX = newX;
            oldY = newY;
            
            repaint();
        }
    }
    
}
