/*
 * @(#) CompositeCanvas2D.java 1.0 99/10/4
 * Copyright (c) 1999 Larry Rodrigues
 */
package com.vistech.imageviewer;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

/** A canvas class for drawing graphics over images.
 * @version 1.0  4 April 2000
 * @author Larry Rodrigues
 */
public class CompositeCanvas2D extends ImageCanvas2D implements DrawingCanvas{
   protected int imageWidth = 0, imageHeight = 0;
   protected int viewerWid =400, viewerHt =300;
   protected int  offsetX = 0, offsetY = 0;
   protected Shape currentShape = null;

   public CompositeCanvas2D(){}

   /** @param img the image over which the graphics are to be drawn.
     * @param wid the width of the canvas.
     * @param ht the height of the canvas.
     **/
   public CompositeCanvas2D(BufferedImage img, int wid, int ht){
      viewerWid = wid;
      viewerHt = ht;
      setSize(wid,ht);
      setBufferedImage(img);
   }

   /** Paints the image with the current display and flip modes.
     * @param img the image to be painted on the canvas.
     * @return true if the drawing is successful.
     */
   public synchronized boolean paintImage(BufferedImage img){
      width = this.getBounds().width;
      height = this.getBounds().height;
      imageWidth = img.getWidth();
      imageHeight = img.getHeight();
      if(imageWidth <0 ) {
        System.out.println("width  <0");
      }
      double magX= (double)width/(double)imageWidth;
      double magY = (double)height/(double)imageHeight;
      int bufferWid =width,bufferHt=height;
      dispModeAtx = new AffineTransform();
      switch(displayMode){
      case DisplayMode.ORIG_SIZE:
        bufferWid = imageWidth;
        bufferHt = imageHeight;
        break;
      case DisplayMode.SCALED:
        double mag= (magY > magX)? magX:magY;
        dispModeAtx.setToScale(mag, mag);
        bufferWid = (int)(imageWidth*mag);
        bufferHt = (int)(imageHeight*mag);
        break;
      case DisplayMode.TO_FIT:
        dispModeAtx.setToScale(magX, magY);
        bufferWid = width;
        bufferHt = height;
        default:
        break;
      }
      BufferedImage bi = new BufferedImage(bufferWid, bufferHt,imageType);
      Graphics2D bigc = bi.createGraphics();
      bigc.drawImage(img, dispModeAtx, this);

      flipAtx = createFlipTransform(flipMode, bufferWid, bufferHt);
      AffineTransformOp atop = new AffineTransformOp(flipAtx, interpolationType);
      offScrImage =  atop.filter(bi, null);
      offScrGc = offScrImage.createGraphics();
      applyTransform(offScrImage, atx);
      repaint();
      return true;
   }

   /** Gets the current transformation that includes the
     * transformation computed for setting the display and flip modes.
     * @return all the transformation that includes the trasformation
     * computed for initial display mode and flip modes.
     */
    public AffineTransform getAllAtx(){
      AffineTransform atx1 = new AffineTransform(dispModeAtx);
      atx1.concatenate(atx);
      return atx1;
   }

   /** Gets the transformation computed for setting the display and flip modes.
     * @return the transformation computed for initial display mode and flip modes.
     */
   public AffineTransform getDispModeAtx(){
      return dispModeAtx;
   }

   /** Draws a shape on the canvas.
     * @param s the Shape to be drawn on the canvas.
     */
    public void drawShape(Shape s){
      currentShape = s;
      dispGc = displayImage.createGraphics();
      dispGc.setColor(Color.red);
      dispGc.draw(s);
      repaint();
   }

   /** Fills the specified shape.
     * @param s the Shape to be filled.
     */
   public void fillShape(Shape s) {
      dispGc = displayImage.createGraphics();
      dispGc.setColor(Color.red);
      dispGc.fill(s);
      repaint();
   }

   /**
     * Erases shapes drawn on the canvas. 
     */
    public void eraseShapes() {
      paintImage();
   }

   public Graphics2D getDisplayedImageGC() {
      return displayImage.createGraphics();
   }

   public BufferedImage getDisplayedImage() {return displayImage;}
   public void reset() {
      repaint();
   }
}
