/*
 * Copyright 1999 by Brown University Computer Science
 * 115 Waterman Street, 4th Floor, Providence, Rhode Island, 02906, U.S.A
 * All rights reserved.
 *
 * Permission is hereby granted for free use and modification of this
 * software.  However, this copyright must remain at all times.
 * Re-distribution is restricted to those with the express written consent
 * of the copyright holder.  Permission can be obtained by mailing
 * cs015headtas@cs.brown.edu.  
 */

package NGP.Containers;

//an import statement means I can refer to a class as if I specified the
//whole package
import java.awt.*;
import com.sun.image.codec.jpeg.*;

/**
 * A Panel that allows Graphics to be drawn.  NGP automatically draws objects
 * by putting them in this special Container.  The DrawingPanel keeps track of
 * the Graphics and tells them to draw when it is appropriate.  It has some
 * special methods, some of which will be necessary for the normal user, some
 * which aren't.
 *
 * @author Matt Chotin (<a href="mailto:mhc@cs.brown.edu">mhc</a>)
 */

public class DrawingPanel extends NGP.Containers.Panel {

  /** This is how we keep track of all our Graphics */
  private java.util.Vector _graphics;

  /**
   * Create a DrawingPanel with the container as its parent.
   *
   * @param container the graphical container for this Panel
   */
  public DrawingPanel(NGP.Container container) {
    super(container);
    this.setLayout(null);
    _graphics = new java.util.Vector();
    this.setDimension(new java.awt.Dimension(10, 10));
  }

  /**
   * Normal users need not use this!
   *<p>
   * Add the Graphic to the vector and add the mouse listener so that
   * it will be able to react.
   *
   * @param g the Graphic to add
   */
  public void addGraphic(NGP.Graphic g) {
    if (!_graphics.contains(g)) {
      _graphics.add(g);
      this.addMouseListener(g);
      this.addMouseMotionListener(g);
    }
  }

  /**
   * Normal users need not use this!
   *<p>
   * Remove the Graphic from the vector and remove the mouse listener so that
   * it won't be able to react.
   *
   * @param g the Graphic to remove
   */
  public void removeGraphic(NGP.Graphic g) {
    _graphics.remove(g);
    this.removeMouseListener(g);
    this.removeMouseMotionListener(g);
  }

  //added by Brent Shields 10-18-99

  /**
    * Normal users need not use this!
    *<p>
    * Remove all of the graphics from the vector and remove their mouse 
    * listeners so that they won't be able to react.
    *
    */

  public void removeAllGraphics() {
    for(int i = 0; i < _graphics.size(); i++) {
      this.removeMouseListener((NGP.Graphic)_graphics.elementAt(i));
      this.removeMouseMotionListener((NGP.Graphic)_graphics.elementAt(i));
      //_graphics.remove(i);
    }
    _graphics.clear();
    this.repaint();
  }

  /**
   * Raise the graphic to be in front of one more graphic on the screen.
   *
   * @param g the Graphic that should be raised.
   * @return a boolean indicating whether it is at the top (true is yes)
   */
  public boolean raiseGraphic(NGP.Graphic g) {
    int cur = _graphics.indexOf(g);
    if (cur == _graphics.size() - 1) return true;
    int raised = cur + 1;
    NGP.Graphic swapWith = (NGP.Graphic)_graphics.set(raised, g);
    _graphics.setElementAt(swapWith, cur);
    this.repaint(g.getBounds());
    return raised ==  _graphics.size() - 1;
  }

  /**
   * Lower the graphic to be behind one more grpahic on the screen.
   *
   * @param g the Graphic that should be lowered.
   * @return a boolean indicating whether it is at the bottom (true is yes).
   */
  public boolean lowerGraphic(NGP.Graphic g) {
    int cur = _graphics.indexOf(g);
    if (cur == 0) return true;
    int lowered = cur - 1;
    NGP.Graphic swapWith = (NGP.Graphic)_graphics.set(lowered, g);
    _graphics.setElementAt(swapWith, cur);
    this.repaint(g.getBounds());
    return lowered == 0;
  }

  /**
   * Normal users need not use this!
   *<p>
   * Loop through all of the NGP.Graphics and paint each one.  If we
	 * are only updating part of the screen, the Graphics instance
	 * will be set correctly so we don't have to worry about it.
   *
   * @param g the Graphics that we use
   */
  public void paintGraphics(Graphics g) {
    ((Graphics2D)g).setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
				     java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
    //loop through all graphics and have them paint on the buffer
    int size = _graphics.size();
    for (int i = 0; i < size; i++) {
      ((NGP.Graphic)(_graphics.elementAt(i))).paint((Graphics2D)g);
    }
  }

  /**
   * Normal users need not use this!
   *<p>
   * Called by AWT to paint the panel.
   * Ours just paints all the contained Graphics.
   *
   * @param g the <code>Graphics</code> we should use
   */
  public void paintComponent(Graphics g) {
		//this makes sure the background is painted
		super.paintComponent(g);
    this.paintGraphics(g);
  }

  /**
   * Give a random point in this DrawingPanel.
   *
   * @return a randomly generated <code>Point</code>
   */
  public java.awt.Point randomPoint() {
    Dimension d = this.getDimension();
    int x = (int)Math.round(Math.random() * d.width);
    int y = (int)Math.round(Math.random() * d.height);
    return new java.awt.Point(x,y);
  }

  /**
   * Save the DrawingPanel as a JPEG to the file that was passed in.
   * You may want to have your application provide a FileDialog which
   * will then call this method passing in the file that was selected.
   *
   * @param file the java.io.File that this image should be saved to
   */
  public void saveAsJPEG(java.io.File file) {
    java.awt.Dimension d = this.getDimension();
    java.awt.image.BufferedImage bimg =
      (java.awt.image.BufferedImage)this.createImage(d.width, d.height);
    java.awt.Graphics g = bimg.getGraphics();
    this.paintGraphics(g);
    java.io.OutputStream out = null;
    try {
      out = new java.io.FileOutputStream(file);
      JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
      JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimg);
      param.setQuality(0.75f,true);
      encoder.encode(bimg,param);
      out.close();
    }
    catch (Exception e) {
      System.out.println("Problem saving as JPEG");
      e.printStackTrace();
    }
  }

}

