/* @(#)LayeredComponent.java   2 May 2007 */

/* Useful imports */

import edu.neu.ccs.*;
import edu.neu.ccs.gui.*;
import edu.neu.ccs.codec.*;
import edu.neu.ccs.console.*;
import edu.neu.ccs.filter.*;
import edu.neu.ccs.jpf.*;
import edu.neu.ccs.parser.*;
import edu.neu.ccs.pedagogy.*;
import edu.neu.ccs.quick.*;
import edu.neu.ccs.util.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
import java.util.*;
import java.math.*;
import java.beans.*;
import java.lang.reflect.*;
import java.net.URL;
import java.util.regex.*;
import java.text.ParseException;


/**
 * <p>Class <code>LayeredComponent</code> encapsulates a
 * <code>JComponent</code> which is in the foreground of the panel,
 * a background object which should be convertible to
 * a <code>Paintable<code>
 * using <code>ComponentFactory.makePaintable</code>,
 * a <code>Paint<code> object to fill in the areas not painted by
 * the background object,
 * an opacity setting for the overall background,
 * and a choice of whether or not the background object should be
 * centered.</p>
 * 
 * <p>The user of this class should not add additional components
 * to an object of this class beyond those installed by the
 * constructor of the object.</p>
 * 
 * @author Richard Rasala
 * @version 2.6.0
 */
public class LayeredComponent
    extends JComponent
{
    JComponent foreground = null;
    
    PaintableComponent lowerLayer = null;
    
    Paintable paintable = null;
    
    XPoint2D corner = null;
    
    Tile tile1 = null;
    Tile tile2 = null;
    Tile tile3 = null;
    
    boolean centered = false;
    
    /**
     * <p>Constructs a <code>LayeredComponent</code>.</p>
     * 
     * <p>The <code>foreground</code> object is a <code>JComponent</code>
     * that will be in the forground of the panel.  This object must be
     * non-<code>null</code>.  The size of the panel will be determined
     * by the preferred size of the foreground.</p>
     * 
     * <p>The <code>background</code> object is an object which should
     * either be <code>null</code> or be an object that is convertible
     * to a <code>Paintable</code> using
     * <code>ComponentFactory.makePaintable</code>.</p>
     * 
     * <p>The <code>paint</code> object is an object which should either
     * be <code>null</code> or be a <code>Paint</code> object.</p>
     * 
     * <p>The <code>opacity</code> parameter determines the opacity to
     * use when painting with the background and the paint.</p>
     * 
     * <p>The <code>centered</code> parameter determines whether the
     * background should be centered relative to the foreground or
     * should simply be painted in its default position.</p>
     * 
     * <p>When the panel is rendered, it is first painted with the paint
     * if that is non-<code>null</code>, then painted by the background
     * if that is non-<code>null</code>.  Both operations are affected
     * by the opacity.  After this, the foreground is rendered.  In
     * order to allow the background painting to be visible, the call
     * <code>foreground.setOpaque(false)</code> is made internally.</p>
     * 
     * <p>If both the background and paint are <code>null</code>, there
     * is no particular reason to use this class.</p>
     */
    public LayeredComponent
        (JComponent foreground,
         Object     background,
         Paint      paint,
         float      opacity,
         boolean    centered)
    {
        if (foreground == null) {
            String message =
                "Null foreground component passed to LayeredComponent";
            
            throw new NullPointerException(message);
        }
        
        this.foreground = foreground;
        
        foreground.setOpaque(false);
        
        tile1 = new Tile();
        tile2 = new Tile(tile1);
        tile3 = new Tile(tile2, paint);
        
        Dimension size = foreground.getPreferredSize();
        
        int w = size.width;
        int h = size.height;
        
        XRect bounds = new XRect(0, 0, w, h);
        
        tile2.setDefaultBounds2D(bounds);
        
        tile3.setOpacity(opacity);
        
        lowerLayer = new PaintableComponent(tile3);
        
        this.centered = centered;
        
        setBackgroundObject(background);
        
        setLayout(new AbsoluteLayout());
        
        add(foreground);
        add(lowerLayer);
    }
    
    
    public float getOpacity() {
        return tile3.getOpacity();
    }
    
    
    public void setOpacity(float opacity) {
        tile3.setOpacity(opacity);
        
        repaint();
    }
    
    
    public boolean isCentered() {
        return centered;
    }
    
    
    public void setCentered(boolean centered) {
        this.centered = centered;
        
        if (paintable == null)
            return;
        
        if (centered) {
            Dimension size = foreground.getPreferredSize();
            
            int w = size.width;
            int h = size.height;
            
            tile1.moveCenterTo(w/2, h/2);
        }
        else {
            tile1.moveCornerTo(corner);
        }
        
        repaint();
    }
    
    
    public void setBackgroundObject(Object background) {
        paintable = ComponentFactory.makePaintable(background);
        
        if (paintable != null)
            corner = paintable.getCorner();
        
        tile1.setPaintable(background);
        
        setCentered(centered);
    }
    
}

