/*
 * @(#)ComponentFactory.java    2.4.0   22 September 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 javax.swing.*;
import java.awt.geom.*;

/**
 * <p>
 * <code>ComponentFactory</code> has 3 <i>static</i> methods that create
 * gui or graphical objects from more general objects.
 * </p>
 *
 * <ul>
 *   <li><code>makeComponent</code> that constructs a <CODE>Component</CODE>
 *       from an <CODE>Object</CODE></li>
 *   <li><code>makeIcon</code> that constructs an <CODE>Icon</CODE>
 *       from an <CODE>Object</CODE></li>
 *   <li><code>makePaintable</code> that constructs a <CODE>Paintable</CODE>
 *       from an <CODE>Object</CODE></li>
 * </ul>
 *
 * <p>
 * The first two methods both make certain specific attempts to convert a
 * general <CODE>Object</CODE> into the desired type.  If these attempts
 * fail then the methods use the <code>makePaintable</code> method to try
 * to convert the <CODE>Object</CODE> into a <CODE>Paintable</CODE>.  If
 * that attempt succeeds then the <CODE>Paintable</CODE> is placed
 * into a <CODE>PaintableComponent</CODE>.  On the other hand, if this
 * final attempt fails then <code>null</code> is returned.
 * </p>
 *
 * @author  Richard Rasala
 * @version 2.4.0
 * @since   2.0
 */
public class ComponentFactory {

    /**
     * <p>Returns a <code>Component</code> associated with the given
     * object.</p>
     * 
     * <p>
     * The table below shows more about how <code>makeComponent</code> works.
     * </p>
     * 
     * <table border=2 cellpadding=2>
     *   <tr>
     *     <td><i>Argument</i></td>
     *     <td><i>Return</i></td>
     *   </tr>
     *   <tr>
     *     <td><code>Component</code></td>
     *     <td>The same <code>Component</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>String</code></td>
     *     <td><code>Annotation</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Icon</code></td>
     *     <td><code>Annotation</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Action</code></td>
     *     <td><code>JButton</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Paint</code></td>
     *     <td><code>PaintSwatch</code></td>
     *   </tr>
     *   <tr>
     *     <td>
     *       <table>
     *         <tr><td><i>converts to</i></td></tr>
     *         <tr><td><code>Paintable</code></td></tr>
     *       </table>
     *     </td>
     *     <td><code>PaintableComponent</code></td>
     *   </tr>
     *   <tr>
     *     <td><i>otherwise</i></td>
     *     <td><code>null</code></td>
     *   </tr>
     * </table>
     *
     * @param o the object to make into a Component
     */
    public static Component makeComponent(Object o) {
        if (o == null)
            return null;
        
        if (o instanceof Component)
            return (Component) o;
        
        if (o instanceof String)
            return new Annotation((String) o);
        
        if (o instanceof Icon)
            return new Annotation((Icon) o);
        
        if (o instanceof Action)
            return new JButton((Action) o);
        
        if (o instanceof Paint)
            return new PaintSwatch((Paint) o);
        
        Object p = makePaintable(o);
        
        if (p instanceof Paintable)
            return new PaintableComponent((Paintable) p);
        
        return null;
    }
    
    
    /**
     * <p>Returns an <code>Icon</code> associated with the given
     * object.</p>
     * 
     * <p>
     * The table below shows more about how <code>makeIcon</code> works.
     * </p>
     * 
     * <table border=2 cellpadding=2>
     *   <tr>
     *     <td><i>Argument</i></td>
     *     <td><i>Return</i></td>
     *   </tr>
     *   <tr>
     *     <td><code>Icon</code></td>
     *     <td>The same <code>Icon</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Paint</code></td>
     *     <td><code>PaintSwatch</code></td>
     *   </tr>
     *   <tr>
     *     <td>
     *       <table>
     *         <tr><td><i>converts to</i></td></tr>
     *         <tr><td><code>Paintable</code></td></tr>
     *       </table>
     *     </td>
     *     <td><code>PaintableComponent</code></td>
     *   </tr>
     *   <tr>
     *     <td><i>otherwise</i></td>
     *     <td><code>null</code></td>
     *   </tr>
     * </table>
     *
     * @param o the object to make into an Icon
     */
    public static Icon makeIcon(Object o) {
        if (o == null)
            return null;
        
        if (o instanceof Icon)
            return ((Icon) o);
        
        if (o instanceof Paint)
            return new PaintSwatch((Paint) o);
        
        Object p = makePaintable(o);
        
        if (p instanceof Paintable)
            return new PaintableComponent((Paintable) p);
        
        return null;
    }
    
    
    /**
     * <p>Returns a <code>Paintable</code> associated with the given
     * object.</p>
     * 
     * <p>
     * The table below shows more about how <code>makePaintable</code> works.
     * </p>
     * 
     * <table border=2 cellpadding=2>
     *   <tr>
     *     <td><i>Argument</i></td>
     *     <td><i>Return</i></td>
     *   </tr>
     *   <tr>
     *     <td><code>Paintable</code></td>
     *     <td>The same <code>Paintable</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Shape</code></td>
     *     <td><code>ShapePaintable</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>PathList</code></td>
     *     <td><code>ShapePaintable</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Image</code></td>
     *     <td><code>ImagePaintable</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>ImageIcon</code></td>
     *     <td><code>ImagePaintable</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>String</code></td>
     *     <td><code>TextPaintable</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Point2D</code></td>
     *     <td><code>PointPaintable</code></td>
     *   </tr>
     *   <tr>
     *     <td><code>Object[]</code></td>
     *     <td><code>PaintableSequence</code></td>
     *   </tr>
     *   <tr>
     *     <td><i>otherwise</i></td>
     *     <td><code>null</code></td>
     *   </tr>
     * </table>
     *
     * @param o the object to make into a Paintable
     */
    public static Paintable makePaintable(Object o) {
        if (o == null)
            return null;
        
        if (o instanceof Paintable)
            return ((Paintable) o);
        
        if (o instanceof Image)
            return new ImagePaintable((Image) o);
        
        if (o instanceof ImageIcon)
            return new ImagePaintable((ImageIcon) o);
        
        if (o instanceof PathList)
            o = ((PathList) o).makeShape();
        
        if (o instanceof Shape)
            return new ShapePaintable((Shape) o);
        
        if (o instanceof String)
            return new TextPaintable((String) o);
        
        if (o instanceof Point2D) {
            PointPaintable pp = new PointPaintable();
            pp.setPoint((Point2D) o);
            return pp;
        }
        
        if (o instanceof Object[])
            return new PaintableSequence((Object[]) o);
        
        return null;
    }
}
