
//Title:        Zoomable Panel
//Version:      
//Copyright:    Copyright (c) 1999
//Author:       John Taylor
//Company:
//Description:  Panel which displays an image and allows
//the user to zoom in.

package zoomPanelBean;

import java.awt.*;
//import javax.swing.*;

public class ZoomPanelBean extends Panel {

  /** Initializes the Form */
  private Image currentImage;
  private Graphics imageGraphics;
  private boolean mouseIsDown = false;
  private int startX;
  private int startY;
  private int endX;
  private int endY;

  private void initComponents () {
    setBackground (java.awt.Color.black);
    setForeground (java.awt.Color.red);
    addMouseListener (new java.awt.event.MouseAdapter () {
        public void mousePressed (java.awt.event.MouseEvent evt) {
          formMousePressed (evt);
        }
        public void mouseReleased (java.awt.event.MouseEvent evt) {
          formMouseReleased (evt);
        }
      }
    );
    addMouseMotionListener (new java.awt.event.MouseMotionAdapter () {
        public void mouseDragged (java.awt.event.MouseEvent evt) {
          formMouseDragged (evt);
        }
      }
    );
    setLayout (new java.awt.FlowLayout ());
  }


  private void formMouseDragged (java.awt.event.MouseEvent evt) {
//    label1.setText(Integer.toString(evt.getModifiers());
//    label2.setText(Integer.toString(java.awt.event.MouseEvent.BUTTON1_MASK));
//    if ((evt.getModifiers() & java.awt.event.MouseEvent.BUTTON1_MASK)!=0) {
    //button 1 only
    endX=evt.getX();
    endY=evt.getY();
    repaint();
//    }
  }


  private void formMouseReleased (java.awt.event.MouseEvent evt) {
    if ((evt.getModifiers() & java.awt.event.MouseEvent.BUTTON1_MASK)!=0) {
//button 1 only
    mouseIsDown=false;
    double  newLogicalXstart, newLogicalXend;
    double newLogicalYstart, newLogicalYend;
    double theta;
    if ((startX==endX) && (startY==endY)) {
    //zoom in a factor of 2 on current point
      startX-=(double) currentImage.getWidth(this)/4;
      endX+=(double) currentImage.getWidth(this)/4;
      startY-=(double) currentImage.getHeight(this)/4;
      endY+=(double) currentImage.getHeight(this)/4;
    }
    if (currentImage!=null){
     theta = (double) startX/ (double) currentImage.getWidth(this);
     newLogicalXstart = (1-theta)*logicalXstart + theta * logicalXend;
     theta = (double) endX/ (double) currentImage.getWidth(this);
     newLogicalXend = (1-theta)*logicalXstart + theta * logicalXend;
     setLogicalXstart(newLogicalXstart);
     setLogicalXend(newLogicalXend);

     theta = (double) startY/ (double) currentImage.getHeight(this);
     newLogicalYstart = (1-theta)*logicalYstart + theta * logicalYend;
     theta = (double) endY/ (double) currentImage.getHeight(this);
     newLogicalYend = (1-theta)*logicalYstart + theta * logicalYend;
     setLogicalYstart(newLogicalYstart);
     setLogicalYend(newLogicalYend);

     propertyChangeSupport.firePropertyChange ("zoom", null, null);
    }
    repaint();
    }
  }

  private void formMousePressed (java.awt.event.MouseEvent evt) {
    if ((evt.getModifiers() & java.awt.event.InputEvent.BUTTON1_MASK)!=0) {
//only interested in button 1
  //   if (!mouseIsDown) {
        startX= evt.getX();
        startY= evt.getY();
        endX=startX;
        endY=startY;
 //    }
        mouseIsDown=true;
   }
    else {
     //button 2 only
        zoomOut(2.0);
    }

  }
  public void update(Graphics g){
    paint(g);
  }
  public void paint(Graphics g) {
    if (currentImage!=null) {
      g.drawImage(currentImage,0,0,this);
    }
    else{
            g.setColor(Color.magenta);
            g.drawString("Null Image",50,50);
            currentImage = createImage(this.getSize().width,this.getSize().height); //default for later
            initImage();
            repaint();
    }
     if (mouseIsDown) {
              g.setColor(Color.white);
              g.setXORMode(Color.black);
              int x,y,h,w;
              x=Math.min(startX,endX);
              y=Math.min(startY,endY);
              w=Math.abs(endX-startX);
              h=Math.abs(endY-startY);
              g.drawRect(x,y,w,h);
     }
  }

  private void initImage() {
    if (currentImage==null) {return;}
    imageGraphics = currentImage.getGraphics();
    imageGraphics.setColor(Color.white);
    imageGraphics.fillOval(0,0,200,200);
    imageGraphics.setColor(Color.green);
    imageGraphics.drawString("No Image",100,100);
  }

  public void zoomOut(double factor) {
    double xSize=logicalXend-logicalXstart;
    double ySize=logicalYend-logicalYstart;

    setLogicalXstart(logicalXstart - xSize*0.5*(factor-1));
    setLogicalXend(logicalXend + xSize*0.5*(factor-1));
    setLogicalYstart(logicalYstart - ySize*0.5*(factor-1));
    setLogicalYend(logicalYend + ySize*0.5*(factor-1));
    propertyChangeSupport.firePropertyChange ("zoom", null, null);
 //   logicalXend += xSize*0.5*(factor-1);
 //   logicalYstart -= ySize*0.5*(factor-1);
 //   logicalYend += ySize*0.5*(factor-1);
  }

////////////////////////////////////////////////////////////
      // Bean code starts below
///////////////////////////////////////////////////////////

/**
 * A ZoomPanelBean JavaBean.
 *
 * @version 1.00
 */


  /** "logicalXstart" property value. */
  private double logicalXstart=0;
  /** "logicalYstart" property value. */
  private double logicalYstart=0;
  /** "logicalXend" property value. */
  private double logicalXend=1.0;
  /** "logicalYend" property value. */
  private double logicalYend=1.0;

  /** The support for property changes. */
  private java.beans.PropertyChangeSupport propertyChangeSupport;
  /**
   * Constructs a new ZoomPanelBean JavaBean.
   */
  public ZoomPanelBean () {
    propertyChangeSupport = new java.beans.PropertyChangeSupport (this);
    initComponents ();
  }

  /**
   * Getter method for the "logicalXstart" property.
   *
   * @return  The current value of this property.
   */
  public double getLogicalXstart () {
    return logicalXstart;
  }

  /**
   * Setter method for the "logicalXstart" property.
   *
   * @param value The new value of this property.
   */
  public void setLogicalXstart (double value) {
    Object oldValue = new Double (logicalXstart);
    logicalXstart = value;
    propertyChangeSupport.firePropertyChange ("logicalXstart", oldValue, new Double (value));
  }

  /**
   * Getter method for the "logicalYstart" property.
   *
   * @return  The current value of this property.
   */
  public double getLogicalYstart () {
    return logicalYstart;
  }

  /**
   * Setter method for the "logicalYstart" property.
   *
   * @param value The new value of this property.
   */
  public void setLogicalYstart (double value) {
    Object oldValue = new Double (logicalYstart);
    logicalYstart = value;
    propertyChangeSupport.firePropertyChange ("logicalYstart", oldValue, new Double (value));
  }

  /**
   * Getter method for the "logicalXend" property.
   *
   * @return  The current value of this property.
   */
  public double getLogicalXend () {
    return logicalXend;
  }

  /**
   * Setter method for the "logicalXend" property.
   *
   * @param value The new value of this property.
   */
  public void setLogicalXend (double value) {
    Object oldValue = new Double (logicalXend);
    logicalXend = value;
    propertyChangeSupport.firePropertyChange ("logicalXend", oldValue, new Double (value));
  }

  /**
   * Getter method for the "logicalYend" property.
   *
   * @return  The current value of this property.
   */
  public double getLogicalYend () {
    return logicalYend;
  }

  /**
   * Setter method for the "logicalYend" property.
   *
   * @param value The new value of this property.
   */
  public void setLogicalYend (double value) {
    Object oldValue = new Double (logicalYend);
    logicalYend = value;
    propertyChangeSupport.firePropertyChange ("logicalYend", oldValue, new Double (value));
  }

  /**
   * Setter method for the "currentImage" variable.
   *
   * @param value The new value of this property.
   */
  public void setCurrentImage (Image theImage) {
    currentImage = theImage;
    repaint();
  }
  public void reset() {
    setLogicalXstart(0.0);
    setLogicalXend(1.0);
    setLogicalYstart(0.0);
    setLogicalYend(1.0);
    propertyChangeSupport.firePropertyChange ("reset", null, null);
  }

  /**
   * Add a PropertyChangeListener to the listener list.
   *
   * @param listener  The PropertyChangeListener to be added.
   */
  public void addPropertyChangeListener (java.beans.PropertyChangeListener listener) {
    propertyChangeSupport.addPropertyChangeListener (listener);
  }

  /**
   * Remove a PropertyChangeListener from the listener list.
   *
   * @param listener  The PropertyChangeListener to be removed.
   */
  public void removePropertyChangeListener (java.beans.PropertyChangeListener listener) {
    propertyChangeSupport.removePropertyChangeListener (listener);
  }

}
