/*
 * @(#)VCL.java    2.x.x   17 September 2006
 *
 * Copyright 2006
 * 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 edu.neu.ccs.*;
import edu.neu.ccs.gui.*;
import edu.neu.ccs.util.*;

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

/**
 * <p>Class <code>VCL</code> displays the named colors as defined
 * in class <code>Colors</code> using a square color swatch and 3
 * labels with the name, the RGBA value, and the hex color value.</p>
 * 
 * <p>The class also provides a <code>ColorView</code> so one can
 * experiment with colors defined by RGBA or hex.</p>
 * 
 * <p>The programmer has some control of the swatch size and pane
 * height.</p>
 *
 * <p>Although this panel is intended primarily for user
 * information, it is possible to use this panel as a control
 * by querying the <code>ColorView</code> state or
 * by attaching listeners to the <code>ColorView</code>
 * that is returned by <code>getColorView()</code>.</p>
 * 
 * <p>This class is an elaboration of the class
 * <code>VisualColorList</code> in JPT and is likely
 * to replace that class in the next release of JPT.</p>
 * 
 * @author  Richard Rasala
 */

public class VCL extends DisplayPanel {
    
    /** The minimum swatch size. */
    private static final int MIN_SWATCH = 20;
    
    /** The default swatch size. */
    private static final int DEF_SWATCH = 25;
    
    /** The maximum swatch size. */
    private static final int MAX_SWATCH = 50;
    
    
    /** The standard border size. */
    private static final int BORDER_SIZE =
        PaintSwatch.BORDER_SIZE;
    
    /** The standard swatch border. */
    private static final Border BORDER =
        PaintSwatch.BLACK_BORDER;
    
    
    /** The internal table panel horizontal gap. */
    private static final int HGAP = 12;
    
    /** The internal table panel vertical gap. */
    private static final int VGAP = 6;
    
    
    /** The maximum width of the viewport of the list scroll pane. */
    private static final int MAX_WIDTH  = 720;  
    
    /** The minimum height of the viewport of the list scroll pane. */
    private static final int MIN_HEIGHT = 120;
    
    /** The default height of the viewport of the list scroll pane. */
    private static final int DEF_HEIGHT = 525;
    
    /** The maximum height of the viewport of the list scroll pane. */
    private static final int MAX_HEIGHT = 800;
    
    
    /**
     * The swatch size that must be between
     * MIN_SWATCH and MAX_SWATCH.
     */
    private int swatchSize = DEF_SWATCH;
    
    /**
     * The pane height that must be between
     * MIN_HEIGHT and MAX_HEIGHT.
     */
    private int paneHeight = DEF_HEIGHT;
    
    
    /** The array of color names. */
    private String[] nameArray = null;
    
    
    /** The array of color rgba values. */
    private String[] rgbaArray = null;
    
    
    /** The array of color rgba values in hex. */
    private String[] hexArray = null;
    
    
    /** The color scroll pane. */
    private JPTScrollPane colorPane = null;
    
    
    /** The color view for experiments. */
    private ColorView colorView = null;
    
    
    /**
     * <p>The constructor that creates a <code>VCL</code>
     * using a swatch size of 25 and a scroll pane height
     * of 525.</p>
     *
     * <p>Additional height is used for the color view.</p>
     */
    public VCL() {
        this(DEF_SWATCH, DEF_HEIGHT);
    }
    
    
    /**
     * <p>The constructor that creates a <code>VCL</code>
     * using the given swatch size and a scroll pane height
     * of 525.</p>
     *
     * <p>The swatch size will be forced to the range 20-50
     * before usage.</p>
     *
     * <p>Additional height is used for the color view.</p>
     *
     * @param swatchSize the desired swatch size
     */
    public VCL(int swatchSize) {
        this(swatchSize, DEF_HEIGHT);
    }
    
    
    /**
     * <p>The constructor that creates a <code>VCL</code>
     * using a the given swatch size and the given scroll
     * pane height.</p>
     *
     * <p>The swatch size will be forced to the range 20-50
     * before usage.</p>
     *
     * <p>The pane height will be forced to the range 120-800
     * before usage.</p>
     *
     * <p>Additional height is used for the color view.</p>
     *
     * @param swatchSize the desired swatch size
     * @param paneHeight the desired pane height
     */
    public VCL(int swatchSize, int paneHeight) {
        adjustGeometricParameters(swatchSize, paneHeight);
        
        fillStringArrays();
        
        colorPane = makeColorPane();
        
        colorView = makeColorView();
        
        Object[] mainStuff = { colorPane, colorView };
        
        VTable mainTable = new VTable(mainStuff, HGAP, VGAP, CENTER);
        
        add(mainTable);
        
        
        /**
        
        // Debugging code to test the size of the main table
        
        Dimension d = table.getPreferredSize();
        
        String message =
            "Width = " + d.width + " Height = " + d.height;
        
        GeneralDialog.showOKDialog(message, "");
        
        */
    }
    
    
    /**
     * <p>Returns a reference to the <code>ColorView</code> object
     * used within this panel.</p>
     * 
     * <p>Although this panel is intended primarily for user
     * information, it is possible to use this panel as a control
     * by querying the <code>ColorView</code> state or
     * by attaching listeners to the <code>ColorView</code>
     * that is returned by this method.</p>
     */
    public ColorView getColorView() { return colorView; }
    
    
    /**
     * Adjust the geometric parameters.
     * 
     * @param swatchSize the desired swatch size
     * @param paneHeight the desired pane height
     */
    private void adjustGeometricParameters
        (int swatchSize, int paneHeight)
    {
        swatchSize = (swatchSize >= MIN_SWATCH)
            ? swatchSize : MIN_SWATCH;
    
        swatchSize = (swatchSize <= MAX_SWATCH)
            ? swatchSize : MAX_SWATCH;
        
        this.swatchSize = swatchSize;
        
        
        paneHeight = (paneHeight >= MIN_HEIGHT)
            ? paneHeight : MIN_HEIGHT;
        
        paneHeight = (paneHeight <= MAX_HEIGHT)
            ? paneHeight : MAX_HEIGHT;
        
        int itemHeight = swatchSize + (2 * BORDER_SIZE) + VGAP;
        
        paneHeight = itemHeight * (paneHeight / itemHeight);
        
        while (paneHeight < MIN_HEIGHT)
            paneHeight += itemHeight;
        
        this.paneHeight = paneHeight;
    }
    
    
    /**
     * Fill the string arrays of color names, rgba values,
     * and rgba values in hex.
     *
     * This information produced by this method
     * is used by makeTableGenerator.
     */
    private void fillStringArrays() {
        nameArray = Colors.getColorNamesAsArray();
        
        int length = nameArray.length;
        
        rgbaArray = new String[length];
        hexArray  = new String[length];
        
        for (int i = 0; i < length; i++) {
            Color color = XColor.getColor(nameArray[i]);
            
            int r = color.getRed();
            int g = color.getGreen();
            int b = color.getBlue();
            int a = color.getAlpha();
            
            String rh = Hex.byteToHex((byte)r); 
            String gh = Hex.byteToHex((byte)g); 
            String bh = Hex.byteToHex((byte)b); 
            
            rgbaArray[i] = r  + "," + g  + "," + b;
            hexArray[i]  = "#" + rh + gh + bh;
            
            if (a < 255) {
                rgbaArray[i] += "," + a;
                
                String ah = Hex.byteToHex((byte)a);
                
                hexArray[i]  += ah;
            }
        }
    }
    
    
    /** Make the scroll pane with named colors. */
    private JPTScrollPane makeColorPane() {
        // use the string arrays to define the table generator
        TableGenerator generator =
            makeTableGenerator(nameArray, rgbaArray, hexArray);
        
        // make the scroll pane color table panel
        int length = nameArray.length;
        
        TablePanel colorPanel =
            new TablePanel(generator, length, 4, HGAP, VGAP, CENTER);
        
        // make the enclosing scroll pane
        JPTScrollPane colorPane = new JPTScrollPane(colorPanel);
        
        colorPane.boundViewportPreferredSize(MAX_WIDTH, paneHeight);
        
        // add border to scroll pane
        Border border = Borders.sandwich
            (Borders.title(" The Standard Named Colors "),
             Borders.empty(4));
        
        colorPane.setBorder(border);
        
        return colorPane;
    }
    
    
    /** Make the color view pane for experiments. */
    private ColorView makeColorView() {
        int size = this.MAX_SWATCH;
        
        Dimension dimension = new Dimension(size, size);
        
        ColorView colorView =
            new ColorView(Color.black, true, dimension);
        
        // add border to color view
        Border border = Borders.sandwich
            (Borders.title(" Color View for Experiments "),
             Borders.empty(4));
        
        colorView.setBorder(border);
        
        return colorView;
    }
    
    
    /**
     * The method to create a swatch based on the given color name
     * and the encapsulated swatch size.
     *
     * This method is used by makeTableGenerator.
     *
     * @param name a color name in the table in class Colors
     */
    private PaintSwatch makeSwatch(String name) {
        return new PaintSwatch
            (Colors.getColorFromName(name), swatchSize, swatchSize, BORDER);
    }
    
    
    /**
     * The method to construct the table generator for the color table.
     * 
     * @param nameArray the array of color names
     * @param rgbaArray the array of color rgba values
     * @param hexArray  the array of color rgba values in hex
     * @return
     */
    private TableGenerator makeTableGenerator
        (final String[] nameArray,
         final String[] rgbaArray,
         final String[] hexArray)
    {
        return new TableGenerator() {
            public Object makeContents(int row, int col) {
                int length = nameArray.length;
                
                if ((row < 0) || (row >= length))
                    return null;
                
                switch (col) {
                    case 0:
                        return makeSwatch(nameArray[row]);
                
                    case 1:
                        return new JLabel(nameArray[row]);
                
                    case 2:
                        return new JLabel(rgbaArray[row]);
                
                    case 3:
                        return new JLabel(hexArray[row]);
                
                    default:
                        return null;
                }
            }
        };
    }
    
    
    public static void main(String[] args) {
        new VCL().frame("Visual Color List");
    }
    
}

