
/*
   An applet showing a red square and a blue square that the user
   can drag with the mouse.   The user can drag a square off
   the applet and drop them.  It will jump back to its starting point.
   This applet does uses double buffering. Double-buffer is handled by
   the update() method.   NonDoubleBufferedDrag is a non-double-buffered
   version of this applet.
*/

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class DoubleBufferedDrag extends Applet
                implements MouseListener, MouseMotionListener {
   

   int x1, y1;   // Coords of top-left corner of the red square.
   int x2, y2;   // Coords of top-left corner of the blue square.
   
   /* Some variable used for double-buffering */
   
   Image OSC;  // The off-screen canvas (created and used in update()).
   
   int widthOfOSC, heightOfOSC;  // Current widht and height of OSC.  These
                                 // are checked against the size of the applet,
                                 // to detect any change in the applet's size.
                                 // If the size has changed, a new OSC is created.
   
   /* Some variables used during dragging */
   
   boolean dragging;      // Set to true when a drag is in progress.
   
   boolean dragRedSquare; // True if red square is being dragged, false
                          //    if blue square is being dragged.
                          
   int offsetX, offsetY;  // Offset of mouse-click coordinates from 
                          //   top-left corner of the square that was
                          //   clicked.
                          
   public void init() {
         // Initialize the applet by putting the squares in a
         // starting position, setting a background color, and
         // setting the applet to listen for mouse events on itself.
      x1 = 10;
      y1 = 10;
      x2 = 50;
      y2 = 10;
      setFont( new Font("Serif", Font.BOLD,14) );
      setBackground(Color.lightGray);
      addMouseListener(this);
      addMouseMotionListener(this);
   }
   

   public void update(Graphics g) {
        // To implement double-buffering, the update method calls paint to
        // draw the contents of the applet on an off-screen canvas.  Then
        // the canvas is copied onto the screen.  This method is responsible
        // for creating the off-screen canvas.  It will make a new OSC if
        // the size of the applet changes.
      if (OSC == null || widthOfOSC != getSize().width || heightOfOSC != getSize().height) {
             // Create the OSC, or make a new one if applet size has changed.
         OSC = null;  // (If OSC already exists, this frees up the memory.)
         OSC = createImage(getSize().width, getSize().height);
         widthOfOSC = getSize().width;
         heightOfOSC = getSize().height;
      }
      Graphics OSG = OSC.getGraphics();  // Graphics context for drawing to OSC.
      OSG.setColor(getBackground());
      OSG.fillRect(0, 0, widthOfOSC, heightOfOSC);
      OSG.setColor(getForeground());
      OSG.setFont(getFont());
      paint(OSG);  // Draw applet contents to OSC.
      g.drawImage(OSC,0,0,this);  // Copy OSC to screen.
   }
                

   public void paint(Graphics g) {
          // Draw the two squars and a black frame around the applet.
      g.setColor(Color.red);
      g.fillRect(x1, y1, 30, 30);
      g.setColor(Color.blue);
      g.fillRect(x2, y2, 30, 30);
      g.setColor(Color.black);
      g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
      g.drawString("Double-buffered", 10, getSize().height - 10);
   }
   

   public void mousePressed(MouseEvent evt) { 
          // Respond when the user presses the mouse on the applet.
          // Check which square the user clicked, if any, and start
          // dragging that square.
   
      if (dragging)  // Exit if a drag is already in progress.
         return;
         
      int x = evt.getX();  // Location where user clicked.
      int y = evt.getY();
      
      if (x >= x2 && x < x2+30 && y >= y2 && y < y2+30) {
             // It's the blue square (which should be checked first,
             // since it's in front of the red square.)
         dragging = true;
         dragRedSquare = false;
         offsetX = x - x2;  // Distance from corner of square to click point.
         offsetY = y - y2;
      }
      else if (x >= x1 && x < x1+30 && y >= y1 && y < y1+30) {
             // It's the red square.
         dragging = true;
         dragRedSquare = true;
         offsetX = x - x1;  // Distance from corner of square to click point.
         offsetY = y - y1;
      }

   }


   public void mouseReleased(MouseEvent evt) { 
          // Dragging stops when user releases the mouse button.
          // If sqaure is (almost) off the screen, move it back to
          // its starting point.
       dragging = false;
       if (dragRedSquare) {
          if (x1 + 30 < 3 || x1 > getSize().width - 3 
                                       || y1 + 30 < 3 || y1 > getSize().height - 3) {
              x1 = 10;
              y1 = 10;
          }
       }
       else {
          if (x2 + 30 < 3 || x2 > getSize().width - 3 
                                       || y2 + 30 < 3 || y2 > getSize().height - 3) {
              x2 = 50;
              y2 = 10;
          }
       }
       repaint();
   }


   public void mouseDragged(MouseEvent evt) { 
           // Respond when the user drags the mouse.  If a square is 
           // not being dragged, then exit.  Otherwise, change the position
           // of the square that is being dragged to match the position
           // of the mouse.  Note that the corner of the square is place
           // in the same postion with respect to the mouse that it had
           // when the user started dragging it.
       if (dragging == false)  
         return;
       int x = evt.getX();
       int y = evt.getY();
       if (dragRedSquare) {  // Move the red square.
          x1 = x - offsetX;
          y1 = y - offsetY;
       }
       else {   // Move the blue square.
          x2 = x - offsetX;
          y2 = y - offsetY;
       }
       repaint();
   }


   public void mouseMoved(MouseEvent evt) { }
   public void mouseClicked(MouseEvent evt) { }
   public void mouseEntered(MouseEvent evt) { }
   public void mouseExited(MouseEvent evt) { }


} // end class DragTwoSquares
