/*
 * @(#)ImageViewerBase.java    2.3.3  2 January 2005
 *
 * Copyright 2005
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */

package edu.neu.ccs.gui;

import java.awt.*;
import java.awt.geom.*;


/**
 * <p>Class <code>ImageViewerBase</code> is the base class for building
 * an image viewer for local image files (<code>ImageViewer</code>) and
 * an image viewer for files on the web (<code>WebImageViewer</code>).</p>
 *
 * <p>Although this class is not abstract, it cannot be instantiated in
 * a direct fashion since its constructor is protected.</p>
 *
 * @author  Richard Rasala
 * @version 2.3.3
 * @since   2.3.3
 */
public class ImageViewerBase extends DisplayPanel {
    
    /**
     * The array of image file names for the images to be viewed;
     * this data MUST be set by a derived class
     * prior to a call to the method <code>makeGUI</code>.
     */
    protected String[] imageFileNames;
    
    /**
     * The array of <code>ImagePaintableLite</code> objects that encapsulate
     * the list of references to the images to be viewed;
     * this data MUST be set by a derived class
     * prior to a call to the method <code>makeGUI</code>.
     */
    protected ImagePaintableLite[] paintables;
    
    /**
     * The maximum width of the scrollpane viewport;
     * this data is calculated in the method <code>makeGUI</code>.
     */
    protected int X_MAX = 0;
    
    /**
     * The maximum height of the scrollpane viewport;
     * this data is calculated in the method <code>makeGUI</code>.
     */
    protected int Y_MAX = 0;
    
    /**
     * The maximum height of a scaled image in the scrollpane viewport;
     * this data is calculated in the method <code>makeGUI</code> and
     * is designed to ensure that if an image is scaled then both the
     * image and its labels may be viewed on screen at once.
     */
    protected int Y_MAX_SMALL = 0;
    
    
    /** The protected default constructor. */
    protected ImageViewerBase() { }
    
    
    /**
     * <p>Returns the scrollpane that contains a vertical list of images
     * together with labels that give the image file name, the index of
     * the image in the list, and the image dimensions;
     * the autoscale parameter determines if the images should be scaled
     * to fit on the screen;
     * this method must be called by a derived class to create the GUI.</p>
     *
     * @param autoscale whether or not to scale images to fit on screen
     * @return a scrollpane with a vertical list of annotated images
     */
    protected JPTScrollPane makeGUI(boolean autoscale) {
        Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
        
        X_MAX = size.width  - 150;
        Y_MAX = size.height - 150;
        
        Y_MAX_SMALL = Y_MAX - 2 * getAnnotationHeight();
        
        int length = imageFileNames.length;
        
        TablePanel panel = new TablePanel(length, 1, 0, 0, CENTER);
        
        for (int i = 0; i < length; i++)
            panel.addObject(makeInnerGUI(i, autoscale), i, 0);
        
        Dimension dimension = panel.getPreferredSize();
        
        dimension.width  =
            (dimension.width  <= X_MAX) ? dimension.width : X_MAX;
        
        dimension.height =
            (dimension.height <= Y_MAX) ? dimension.height: Y_MAX;
        
        JPTScrollPane scrollpane = new JPTScrollPane(panel);
        
        scrollpane.boundViewportPreferredSize(dimension);
        
        return scrollpane;
    }
    
    
    /**
     * <p>Returns a table panel for the image at the given index;
     * the panel contains the image and labels with the image file name,
     * the index of the image in the list, and the image dimensions;
     * the autoscale parameter determines if the image should be scaled
     * to fit on the screen;
     * this method is called automatically by <code>makeGUI</code>.</p>
     *
     * @param autoscale whether or not to scale images to fit on screen
     * @return a table panel with the image and its labels
     */
    protected TablePanel makeInnerGUI(int index, boolean autoscale) {
        Paintable paintable = paintables[index];
        
        int width  = paintables[index].getImageWidth();
        int height = paintables[index].getImageHeight();
        
        String title1 = imageFileNames[index];
        String title2 = "#" + index + ": " + width + " x " + height;
        
        if (autoscale) {
            if ((width > X_MAX) || (height > Y_MAX_SMALL)) {
                double a = ((double) X_MAX)       / ((double) width);
                double b = ((double) Y_MAX_SMALL) / ((double) height);
                
                double s = Math.min(a, b);
                
                AffineTransform scaleTransform = TransformFactory.scale(0, 0, 0, s, s);
                
                paintable = new Tile(paintable, scaleTransform);
            }
        }
        
        return new TablePanel(
            new Object[] { paintable, title1, title2 },
            VERTICAL, 0, 0, CENTER);
    }
    
    
    /**
     * <p>Returns the height of an annotation in the current look and feel;
     * this convenience method is used by <code>makeGUI</code>.</p>
     *
     * @return the height of an annotation in the current look and feel
     */
    protected static int getAnnotationHeight() {
        Annotation test = new Annotation("Xy");
        
        Dimension size = test.getPreferredSize();
        
        return size.height;
    }
    
}
