/*
 * @(#)JPTScrollPane.java    2.3.5  19 February 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 edu.neu.ccs.util.*;

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

/**
 * <P>Class <CODE>JPTScrollPane</CODE> extends <CODE>JScrollPane</CODE>
 * by adding methods that help control the preferred size of the
 * <CODE>JViewport</CODE> window.</P>
 *
 * @author  Richard Rasala
 * @version 2.3.5
 * @since   1.0
 */
public class JPTScrollPane extends JScrollPane
    implements JPTConstants
{
    
    /**
     * <P>Creates an empty (no viewport view) <CODE>JPTScrollPane</CODE>
     * where both horizontal and vertical scrollbars appear when needed.</P>
     *
     * @see #JPTScrollPane(Component)
     * @see #JPTScrollPane(int, int)
     * @see #JPTScrollPane(Component, int, int)
     */
    public JPTScrollPane() { super(); }
    
    
    /**
     * <P>Creates a <CODE>JPTScrollPane</CODE> that displays the contents
     * of the specified component,
     * where both horizontal and vertical scrollbars appear whenever the
     * component's contents are larger than the view.</P>
     *
     * @param view the component to display in the scrollpane's viewport
     * @see #JPTScrollPane()
     * @see #JPTScrollPane(int, int)
     * @see #JPTScrollPane(Component, int, int)
     */
    public JPTScrollPane(Component view) { super(view); }
    
    
    /**
     * <P>Creates an empty (no viewport view) <CODE>JPTScrollPane</CODE> whose
     * scrollbars are displayed in accordance with the scrollbar policies.</P>
     *
     * @param vsbPolicy an integer that specifies the vertical   scrollbar policy
     * @param hsbPolicy an integer that specifies the horizontal scrollbar policy
     * @see #JPTScrollPane()
     * @see #JPTScrollPane(Component)
     * @see #JPTScrollPane(Component, int, int)
     * @see JScrollPane#setVerticalScrollBarPolicy(int)
     * @see JScrollPane#setHorizontalScrollBarPolicy(int)
     */
    public JPTScrollPane(int vsbPolicy, int hsbPolicy) {
        super(vsbPolicy, hsbPolicy);
    }
    
    
    /**
     * <P>Creates a <CODE>JPTScrollPane</CODE> that displays the view component
     * in a viewport whose view position can be controlled with a pair of
     * scrollbars that are displayed in accordance with the scrollbar policies.</P>
     *
     * @param view      the component to display in the scrollpane's viewport
     * @param vsbPolicy an integer that specifies the vertical   scrollbar policy
     * @param hsbPolicy an integer that specifies the horizontal scrollbar policy
     * @see #JPTScrollPane()
     * @see #JPTScrollPane(Component)
     * @see #JPTScrollPane(int, int)
     * @see JScrollPane#setVerticalScrollBarPolicy(int)
     * @see JScrollPane#setHorizontalScrollBarPolicy(int)
     */
    public JPTScrollPane(Component view, int vsbPolicy, int hsbPolicy) {
        super(view, vsbPolicy, hsbPolicy);
    }
    
    
    /**
     * <P>Sets the preferred size of the scrollpane's viewport to the given
     * <CODE>Dimension</CODE>.</P>
     *
     * <P>Does nothing if:</P>
     *
     * <UL>
     *   <LI>the scrollpane's viewport is <CODE>null</CODE></LI>
     *   <LI>the given <CODE>Dimension</CODE> is <CODE>null</CODE></LI>
     * </UL>
     *
     * <P>If the scrollpane's viewport is changed after this call then this
     * call will have no further effect.</P>
     *
     * @param d the desired preferred size of the scrollpane's viewport
     * @see #setViewportPreferredSize(int, int)
     */
    public void setViewportPreferredSize(Dimension d) {
        if (d == null)
            return;
        
        setViewportPreferredSize(d.width, d.height);
    }
    
    
    /**
     * <P>Sets the preferred size of the scrollpane's viewport to the given
     * width and height.</P>
     *
     * <P>Does nothing if:</P>
     *
     * <UL>
     *   <LI>the scrollpane's viewport is <CODE>null</CODE></LI>
     * </UL>
     *
     * <P>If the scrollpane's viewport is changed after this call then this
     * call will have no further effect.</P>
     *
     * @param width  the desired preferred width  of the scrollpane's viewport
     * @param height the desired preferred height of the scrollpane's viewport
     * @see #setViewportPreferredSize(Dimension)
     */
    public void setViewportPreferredSize(int width, int height) {
        JViewport viewport = getViewport();
        
        if (viewport == null)
            return;
        
        viewport.setPreferredSize(new Dimension(width, height));
    }
    
    
    /**
     * <P>Bounds the preferred size of the scrollpane's viewport to be no larger
     * than the given <CODE>Dimension</CODE>.</P>
     *
     * <P>Operationally, this method calls <CODE>setViewportPreferredSize</CODE>
     * with a dimension that is the minimum of the given dimension and the
     * preferred size of the viewport's view.</P>
     *
     * <P>Does nothing if:</P>
     *
     * <UL>
     *   <LI>the scrollpane's viewport is <CODE>null</CODE></LI>
     *   <LI>the scrollpane's viewport's view is <CODE>null</CODE></LI>
     *   <LI>the given <CODE>Dimension</CODE> is <CODE>null</CODE></LI>
     * </UL>
     *
     * <P>If the scrollpane's viewport is changed after this call then this
     * call will have no further effect.</P>
     *
     * @param d the desired preferred bound for the scrollpane's viewport
     * @see #setViewportPreferredSize(Dimension)
     * @see #boundViewportPreferredSize(int, int)
     * @see DimensionUtilities#min(Dimension, Dimension)
     */
    public void boundViewportPreferredSize(Dimension d) {
        if (d == null)
            return;
        
        boundViewportPreferredSize(d.width, d.height);
    }
    
    
    /**
     * <P>Bounds the preferred size of the scrollpane's viewport to be no larger
     * than the given width and height.</P>
     *
     * <P>Operationally, this method calls <CODE>setViewportPreferredSize</CODE>
     * with a dimension that is the minimum of the given dimension and the
     * preferred size of the viewport's view.</P>
     *
     * <P>Does nothing if:</P>
     *
     * <UL>
     *   <LI>the scrollpane's viewport is <CODE>null</CODE></LI>
     *   <LI>the scrollpane's viewport's view is <CODE>null</CODE></LI>
     * </UL>
     *
     * <P>If the scrollpane's viewport is changed after this call then this
     * call will have no further effect.</P>
     *
     * @param d the desired preferred bound for the scrollpane's viewport
     * @see #setViewportPreferredSize(int, int)
     * @see #boundViewportPreferredSize(Dimension)
     * @see DimensionUtilities#min(Dimension, Dimension)
     */
    public void boundViewportPreferredSize(int width, int height) {
        JViewport viewport = getViewport();
        
        if (viewport == null)
            return;
        
        Component view = viewport.getView();
        
        if (view == null)
            return;
        
        Dimension d1 = new Dimension(width, height);
        
        Dimension d2;
        
        if (view instanceof Container) {
            d2 = ((Container) view).getPreferredSize();
        }
        else {
            d2 = view.getSize();
        }
        
        setViewportPreferredSize(DimensionUtilities.min(d1, d2));
    }
    
    
    /**
     * <p>Frame this panel in a JPTFrame
     * and open the frame;
     * return the frame constructed.</p>
     *
     * @return the frame constructed
     * @since 2.3.5
     */
    public JPTFrame frame() {
        return frame(null, CENTER, null);
    }
    
    
    /**
     * <p>Frame this panel in a JPTFrame
     * and open the frame;
     * use the given location which should be either
     * <code>CENTER</code> or one of the standard constants
     * for one of the eight compass directions;
     * return the frame constructed.</p>
     *
     * @param location the constant representing the frame location
     * @return the frame constructed
     * @since 2.3.5
     */
    public JPTFrame frame(int location) {
        return frame(null, location, null);
    }
    
    
    /**
     * <p>Frame this panel in a JPTFrame
     * and open the frame;
     * use the given title for the frame;
     * return the frame constructed.</p>
     *
     * @param title the title for the frame
     * @return the frame constructed
     * @since 2.3.5
     */
    public JPTFrame frame(String title) {
        return frame(title, CENTER, null);
    }
    
    
    /**
     * <p>Frame this panel in a JPTFrame
     * and open the frame;
     * use the given title for the frame;
     * use the given location which should be either
     * <code>CENTER</code> or one of the standard constants
     * for one of the eight compass directions;
     * return the frame constructed.</p>
     *
     * @param title    the title for the frame
     * @param location the constant representing the frame location
     * @return the frame constructed
     * @since 2.3.5
     */
    public JPTFrame frame(String title, int location) {
        return frame(title, location, null);
    }
    
    
    /**
     * <p>Frame this panel in a JPTFrame
     * and open the frame;
     * use the given title for the frame;
     * use the given insets to inset the frame in the screen;
     * return the frame constructed.</p>
     *
     * @param title    the title for the frame
     * @param insets   the screen insets to use to adjust the location
     * @return the frame constructed
     * @since 2.3.5
     */
    public JPTFrame frame(String title, Insets insets) {
        return frame(title, CENTER, insets);
    }
    
    
    /**
     * <p>Frame this panel in a JPTFrame
     * and open the frame;
     * use the given title for the frame;
     * use the given location which should be either
     * <code>CENTER</code> or one of the standard constants
     * for one of the eight compass directions;
     * use the given insets to inset the frame in the screen;
     * return the frame constructed.</p>
     *
     * @param title    the title for the frame
     * @param location the constant representing the frame location
     * @param insets   the screen insets to use to adjust the location
     * @return the frame constructed
     * @since 2.3.5
     */
    public JPTFrame frame(String title, int location, Insets insets) {
        return JPTFrame.frame(this, title, location, insets);
    }
    
    
    /**
     * <p>Place this panel in a modal OK dialog
     * and open the dialog;
     * return the dialog constructed.</p>
     *
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog OKDialog() {
        return OKDialog(null);
    }
    
    
    /**
     * <p>Place this panel in a modal OK dialog
     * and open the dialog;
     * use the given title for the dialog;
     * return the dialog constructed.</p>
     *
     * @param title the title for the dialog
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog OKDialog(String title) {
        GeneralDialog dialog = GeneralDialog.makeOKDialog(this, title);
        dialog.setVisible(true);
        return dialog;
    }
    
    
    /**
     * <p>Place this panel in a modal OK-Cancel dialog
     * and open the dialog;
     * return the dialog constructed.</p>
     *
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog OKCancelDialog() {
        return OKCancelDialog(null);
    }
    
    
    /**
     * <p>Place this panel in a modal OK-Cancel dialog
     * and open the dialog;
     * use the given title for the dialog;
     * return the dialog constructed.</p>
     *
     * @param title the title for the dialog
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog OKCancelDialog(String title) {
        GeneralDialog dialog = GeneralDialog.makeOKCancelDialog(this, title);
        dialog.setVisible(true);
        return dialog;
    }
    
    
    /**
     * <p>Place this panel in a modal Yes-No-Cancel dialog
     * and open the dialog;
     * return the dialog constructed.</p>
     *
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog YesNoCancelDialog() {
        return YesNoCancelDialog(null);
    }
    
    
    /**
     * <p>Place this panel in a modal Yes-No-Cancel dialog
     * and open the dialog;
     * use the given title for the dialog;
     * return the dialog constructed.</p>
     *
     * @param title the title for the dialog
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog YesNoCancelDialog(String title) {
        GeneralDialog dialog = GeneralDialog.makeYesNoCancelDialog(this, title);
        dialog.setVisible(true);
        return dialog;
    }
    
    
    /**
     * <p>Place this panel in a modal general dialog
     * and open the dialog;
     * use the action data to define the dialog buttons;
     * return the dialog constructed.</p>
     *
     * <p>The parameter <code>actionData</code> 
     * is an <code>Object[][]</code> array that specifies 
     * each dialog <code>Action</code> in one of the following ways:</p>
     * 
     * <ul>
     *   <li> A subarray { action }             with an <code>Action</code></li>
     *   <li> A subarray { name }               with an action name</li>
     *   <li> A subarray { name, icon }         with an action name and icon</li>
     *   <li> A subarray { action, option }
     *   <li> A subarray { name, option }
     *   <li> A subarray { name, icon, option }
     * </ul>
     *
     * <p>If the option parameter is specified, it must be one of the following
     * values that will determine what is done to the dialog when the action is
     * finished:</p>
     *
     * <ul><code>
     *   <li> DialogAction.KEEP_OPEN</li>
     *   <li> DialogAction.AUTO_CLOSE</li>
     *   <li> DialogAction.SET_CANCEL</li>
     * </code></ul>
     *
     * <p>If the option parameter is not specified, it is taken to be
     * <code>DialogAction.AUTO_CLOSE</code>.</p>
     *
     * @param actionData the action data
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog generalDialog(Object[][] actionData) {
        return generalDialog(null, actionData, null);
    }
    
    
    /**
     * <p>Place this panel in a modal general dialog
     * and open the dialog;
     * use the action data to define the dialog buttons;
     * use the default action object to define the default button;
     * return the dialog constructed.</p>
     *
     * <p>The parameter <code>actionData</code> 
     * is an <code>Object[][]</code> array that specifies 
     * each dialog <code>Action</code> in one of the following ways:</p>
     * 
     * <ul>
     *   <li> A subarray { action }             with an <code>Action</code></li>
     *   <li> A subarray { name }               with an action name</li>
     *   <li> A subarray { name, icon }         with an action name and icon</li>
     *   <li> A subarray { action, option }
     *   <li> A subarray { name, option }
     *   <li> A subarray { name, icon, option }
     * </ul>
     *
     * <p>If the option parameter is specified, it must be one of the following
     * values that will determine what is done to the dialog when the action is
     * finished:</p>
     *
     * <ul><code>
     *   <li> DialogAction.KEEP_OPEN</li>
     *   <li> DialogAction.AUTO_CLOSE</li>
     *   <li> DialogAction.SET_CANCEL</li>
     * </code></ul>
     *
     * <p>If the option parameter is not specified, it is taken to be
     * <code>DialogAction.AUTO_CLOSE</code>.</p>
     *
     * <p>The <code>Object</code> supplied for the default action must either be
     * an <code>Action</code> or a name that is supplied in the action data.  If
     * the parameter is <code>null</code>, no default action is set.</p>
     * 
     * @param actionData    the action data
     * @param defaultAction the default action
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog generalDialog(Object[][] actionData, Object defaultAction) {
        return generalDialog(null, actionData, defaultAction);
    }
    
    
    /**
     * <p>Place this panel in a modal general dialog
     * and open the dialog;
     * use the given title for the dialog;
     * use the action data to define the dialog buttons;
     * return the dialog constructed.</p>
     *
     * <p>The parameter <code>actionData</code> 
     * is an <code>Object[][]</code> array that specifies 
     * each dialog <code>Action</code> in one of the following ways:</p>
     * 
     * <ul>
     *   <li> A subarray { action }             with an <code>Action</code></li>
     *   <li> A subarray { name }               with an action name</li>
     *   <li> A subarray { name, icon }         with an action name and icon</li>
     *   <li> A subarray { action, option }
     *   <li> A subarray { name, option }
     *   <li> A subarray { name, icon, option }
     * </ul>
     *
     * <p>If the option parameter is specified, it must be one of the following
     * values that will determine what is done to the dialog when the action is
     * finished:</p>
     *
     * <ul><code>
     *   <li> DialogAction.KEEP_OPEN</li>
     *   <li> DialogAction.AUTO_CLOSE</li>
     *   <li> DialogAction.SET_CANCEL</li>
     * </code></ul>
     *
     * <p>If the option parameter is not specified, it is taken to be
     * <code>DialogAction.AUTO_CLOSE</code>.</p>
     *
     * @param title      the title for the dialog
     * @param actionData the action data
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog generalDialog(String title, Object[][] actionData) {
        return generalDialog(title, actionData, null);
    }
    
    
    /**
     * <p>Place this panel in a modal general dialog
     * and open the dialog;
     * use the given title for the dialog;
     * use the action data to define the dialog buttons;
     * use the default action object to define the default button;
     * return the dialog constructed.</p>
     *
     * <p>The parameter <code>actionData</code> 
     * is an <code>Object[][]</code> array that specifies 
     * each dialog <code>Action</code> in one of the following ways:</p>
     * 
     * <ul>
     *   <li> A subarray { action }             with an <code>Action</code></li>
     *   <li> A subarray { name }               with an action name</li>
     *   <li> A subarray { name, icon }         with an action name and icon</li>
     *   <li> A subarray { action, option }
     *   <li> A subarray { name, option }
     *   <li> A subarray { name, icon, option }
     * </ul>
     *
     * <p>If the option parameter is specified, it must be one of the following
     * values that will determine what is done to the dialog when the action is
     * finished:</p>
     *
     * <ul><code>
     *   <li> DialogAction.KEEP_OPEN</li>
     *   <li> DialogAction.AUTO_CLOSE</li>
     *   <li> DialogAction.SET_CANCEL</li>
     * </code></ul>
     *
     * <p>If the option parameter is not specified, it is taken to be
     * <code>DialogAction.AUTO_CLOSE</code>.</p>
     *
     * <p>The <code>Object</code> supplied for the default action must either be
     * an <code>Action</code> or a name that is supplied in the action data.  If
     * the parameter is <code>null</code>, no default action is set.</p>
     * 
     * @param title         the title for the dialog
     * @param actionData    the action data
     * @param defaultAction the default action
     * @return the dialog constructed
     * @since 2.3.5
     */
    public GeneralDialog generalDialog
        (String title, Object[][] actionData, Object defaultAction)
    {
        GeneralDialog dialog = new GeneralDialog(this, title, actionData, defaultAction);
        
        dialog.setVisible(true);
        return dialog;
    }
    
    
    /**
     * Refreshes the component by repacking the parent window.
     *
     * @since 2.3.5
     */
    public void refreshComponent() {
        Refresh.packParentWindow(this);
    }
    
}

