/** ImageManipulatorJAI Class
   * @version 1.0  10 apr 2000
   * @author Lawrence Rodrigues
   **/
package com.vistech.jai.render;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.awt.geom.*;
import java.awt.image.renderable.*;
import javax.media.jai.*;
import com.vistech.imageviewer.*;

/** A component class for drawing renderable images. This class is similar to
  * JAIImageCavas except that it takes renderable images as inuts. T
  * The renderable image is painted by the  drawRenderable() method of  Graphics class.
  * @version 1.0 10 Apr 2000
  * @author Lawrence Rodrigues
  **/

public class RenderableImageCanvas extends JComponent implements ScrollController {
   public final static int TO_FIT =0;
   public final static int SCALED = 1;
   public final static int MAX_SIZE = 4;

   protected RenderableImage sourceImage;
   protected AffineTransform atx = new AffineTransform();
   protected boolean imageDrawn = false;
   protected int panX =0, panY =0;
   private Point scrollAnchor  = new Point(0,0);
   protected boolean scrollOn = true;
   protected int viewerWidth = 480, viewerHeight = 400;
   protected Point panOffset = new Point(0,0);
   protected int displayMode = SCALED;
   protected float sourceImageHeight = 1.0f;
   protected float sourceImageWidth = 1.0f;
   protected int maxHeight =1024, maxWidth = 1024;

   public RenderableImageCanvas() {}
   public RenderableImageCanvas(RenderableImage img){
      atx = new AffineTransform();
      setImage(img);
   }

   public boolean isImageDrawn(){ return imageDrawn;}

   public void setDisplayMode(int dispMode) {
      displayMode = dispMode;
      createScalingTransform();
   }
   public int getDisplayMode(){ return displayMode;}

   public void setOrigImageSize(Dimension size){
      maxWidth = size.width;
      maxHeight = size.height;
   }
   public void setImage(RenderableImage rImg){
      sourceImage =  rImg;
      panX =0; panY =0;
      sourceImageHeight = sourceImage.getHeight();
      sourceImageWidth = sourceImage.getWidth();
      createScalingTransform();
      imageDrawn = false;
      repaint();
   }
   protected void createScalingTransform(){
      int wid = viewerWidth, ht = viewerHeight;
      double aspectRatio = sourceImageWidth/sourceImageHeight;
      switch (displayMode) {
        case SCALED:
           if(aspectRatio > 1.00) ht =  (int)(viewerHeight/aspectRatio);
           else wid = (int)(viewerWidth/aspectRatio);
           atx.setToScale(wid/(double)sourceImageWidth,ht*sourceImageHeight);
           break;
         case MAX_SIZE:
           wid = maxWidth; ht =  maxHeight;
           atx.setToScale(maxWidth/(double)sourceImageWidth,maxHeight*sourceImageHeight);
           break;
         case TO_FIT:
           atx.setToScale(viewerWidth/(double)sourceImageWidth,sourceImageHeight*viewerHeight);
           break;
      }
       repaint();
   }

   public void paintComponent(Graphics gc){
      Graphics2D g = (Graphics2D)gc;
      Rectangle rect = this.getBounds();
      if((viewerWidth != rect.width) || (viewerHeight != rect.height)){
         viewerWidth =rect.width;
         viewerHeight = rect.height;
         createScalingTransform();
      }
      if(sourceImage == null) return;
      g.setColor(Color.black);
      g.fillRect(0,0,viewerWidth, viewerHeight);
      try {
        Point2D dest = null;
        dest = atx.inverseTransform(new Point(panX,panY), dest);
        atx.translate(dest.getX(), dest.getY());
        g.drawRenderableImage(sourceImage, atx);
      }catch (Exception e) {}
      imageDrawn = true;
   }

   public void setPanOffset(Point panOffset){
      firePropertyChange("PanOffset",this.panOffset,panOffset);
      this.panOffset = panOffset;
      panX = panOffset.x; panY = panOffset.y;
   }

   public Point getPanOffset(){ return panOffset;}

   public void setScrollOn(boolean onOff){
      scrollOn = onOff;
      panX =0; panY =0;
   }

   public  boolean getScrollOn(){ return scrollOn;}

   public void startScroll(int x, int y){
      scrollAnchor.x = x- panX;
      scrollAnchor.y = y- panY;
      repaint();
   }

   public void scroll(int x, int y){
      if((x <0 )|| (y<0)) return;
      panX = x-scrollAnchor.x;
      panY = y-scrollAnchor.y;
      repaint();
   }

   public void stopScroll(){ setCursor(Cursor.getDefaultCursor());}

   public void pan(double x, double y){
      panX = (int)x; panY = (int)y;
      atx.translate(x,y);
      repaint();
   }

   public void reset(){
      atx = new AffineTransform();
      panX =0; panY =0;
   }
}
