/*
 * @(#)DimensionUtilities.java    1.0  19 February 2001
 *
 * Copyright 2004
 * 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.util;

import java.awt.*;

/**
 * <P>Provides utilities for manipulating 
 * <CODE>Dimension</CODE> objects.</P>
 *
 * @author  Richard Rasala
 * @version 2.2
 * @since   1.0
 */
public class DimensionUtilities {

    /**
     * Returns a new <CODE>Dimension</CODE> object 
     * with the given width and height;
     * if the given width or height is less than zero,
     * it is set to zero.
     *
     * @param width the width for the new <CODE>Dimension</CODE>
     * @param width the height for the new <CODE>Dimension</CODE>
     * @see #createDimension(Dimension)
     */
    public static Dimension createDimension(int width, int height) {
        width  = Math.max(width,  0);
        height = Math.max(height, 0);
        
        return new Dimension(width, height);
    }
    
    /**
     * Returns a new <CODE>Dimension</CODE> object 
     * with the width and height of the given <CODE>Dimension</CODE>;
     * if the given width or height is less than zero,
     * it is set to zero.
     *
     * @param d the <CODE>Dimension</CODE> to be copied
     * @see #createDimension(int, int)
     * @throws NullPointerException 
     *      if the given <CODE>Dimension</CODE> is <CODE>null</CODE>
     */
    public static Dimension createDimension(Dimension d) {
        return createDimension(
            (int)d.getWidth(), (int)d.getHeight());
    }
        
    /**
     * Returns a new <CODE>Dimension</CODE> object
     * with zero width and height.
     *
     * @see #createMinimumDimension()
     */
    public static Dimension createMinimumDimension() {
        return new Dimension(0, 0);
    }
        
    /**
     * Returns a new <CODE>Dimension</CODE> object
     * with the maximum possible width and height.
     *
     * @see #createMaximumDimension()
     */
    public static Dimension createMaximumDimension() {
        return new Dimension(
            Integer.MAX_VALUE, Integer.MAX_VALUE);
    }
        
    /**
     * Returns a new <CODE>Dimension</CODE> object
     * whose width and height are set 
     * to the minimum corresponding values 
     * in the given <CODE>Dimension</CODE> objects.
     *
     * @param d1 one of two Dimension objects
     * @param d2 the other of the two Dimension objects
     * @see #max(Dimension, Dimension)
     * @throws NullPointerException 
     *      if either of the given <CODE>Dimension</CODE> objects
     *      is <CODE>null</CODE>
     */
    public static Dimension min(Dimension d1, Dimension d2) {
        int width = Math.min(
            (int)d1.getWidth(), (int)d2.getWidth());
        int height = Math.min(
            (int)d1.getHeight(), (int)d2.getHeight());
        
        return createDimension(width, height);
    }

    /**
     * Returns a new <CODE>Dimension</CODE> object
     * whose width and height are set 
     * to the maximum corresponding values 
     * in the given <CODE>Dimension</CODE> objects.
     *
     * @param d1 one of two Dimension objects
     * @param d2 the other of the two Dimension objects
     * @see #min(Dimension, Dimension)
     * @throws NullPointerException 
     *      if either of the given <CODE>Dimension</CODE> objects
     *      is <CODE>null</CODE>
     */
    public static Dimension max(Dimension d1, Dimension d2) {
        int width = Math.max(
            (int)d1.getWidth(), (int)d2.getWidth());
        int height = Math.max(
            (int)d1.getHeight(), (int)d2.getHeight());
        
        return createDimension(width, height);
    }
    
    /**
     * Returns a new <CODE>Dimension</CODE> object
     * whose width and height are equal 
     * to the corresponding values 
     * in the given <CODE>Dimension</CODE> object,
     * expanded to include the given <CODE>Insets</CODE>.
     *
     * If the given <CODE>Insets</CODE> are negative
     * with respect to either the <I>x</I> or <I>y</I> direction,
     * the given <CODE>Dimension</CODE> is 
     * neither expanded nor shrinked in that direction.
     *
     * @param d the <CODE>Dimension</CODE> to be copied and expanded
     * @param insets the <CODE>Insets</CODE> to be considered
     * @see #shrink(Dimension, Insets)
     * @throws NullPointerException 
     *      if either the given <CODE>Dimension</CODE> object
     *      or the given <CODE>Insets</CODE> object
     *      is <CODE>null</CODE>
     */
    public static Dimension expand(Dimension d, Insets insets) {
        int width  = (int)d.getWidth();
        int height = (int)d.getHeight();
        int dx = insets.left + insets.right;
        int dy = insets.top + insets.bottom;
        
        if (dx > 0) {
            if (width < (Integer.MAX_VALUE - dx))
                width += dx;
            else
                width = Integer.MAX_VALUE;
        }
        
        if (dy > 0) {
            if (height < (Integer.MAX_VALUE - dy))
                height += dy;
            else
                height = Integer.MAX_VALUE;
        }
        
        return createDimension(width, height);
    }
    
    /**
     * Returns a new <CODE>Dimension</CODE> object
     * whose width and height are equal 
     * to the corresponding values 
     * in the given <CODE>Dimension</CODE> object,
     * shrinked to exclude the given <CODE>Insets</CODE>.
     *
     * If the given <CODE>Insets</CODE> are negative
     * with respect to either the <I>x</I> or <I>y</I> direction,
     * the given <CODE>Dimension</CODE> is 
     * neither expanded nor shrinked in that direction.
     *
     * @param d the <CODE>Dimension</CODE> to be copied and shrinked
     * @param insets the <CODE>Insets</CODE> to be considered
     * @see #expand(Dimension, Insets)
     * @throws NullPointerException 
     *      if either the given <CODE>Dimension</CODE> object
     *      or the given <CODE>Insets</CODE> object
     *      is <CODE>null</CODE>
     */
    public static Dimension shrink(Dimension d, Insets insets) {
        int width  = (int)d.getWidth();
        int height = (int)d.getHeight();
        int dx = insets.left + insets.right;
        int dy = insets.top + insets.bottom;
        
        if (dx > 0) {
            if (width  >  dx)
                width  -= dx;
            else
                width  =  0;
        }
        
        if (dy > 0) {
            if (height >  dy)
                height -= dy;
            else
                height =  0;
        }
        
        return createDimension(width, height);
    }
}
