package cnp.ew.diagram;

import java.awt.*;
import java.util.*;

import cnp.ew.lightweight.*;
import cnp.ew.properties.*;

public abstract class CpAbstractDiagrammableLc extends CpAbstractLc implements CpDiagrammableLc, CpHasProperties
{
    public final static int BACKGROUND_PROP = 100; // Uh, oh, this is like events...
    public final static int FONTNAME_PROP = 101; // Uh, oh, this is like events...

    static Vector properties;

    CpDiagram diagram;


    public CpAbstractDiagrammableLc()
    {
        super();
    }

    public CpAbstractDiagrammableLc(int x, int y, int w, int h)
    {
        super(x, y, w, h);
    }

    public void setDiagram(CpDiagram newDiagram)
    {
        diagram = newDiagram;
    }

    public CpDiagram getDiagram()
    {
        return diagram;
    }

	public Vector getHandles()
	{
	    // If this is slow, we can cache them...
	    Vector v = new Vector();
		v.addElement(new CpSizingHandle(this, CpBasicLocator.rightBottomLocator, CpBasicLocator.leftTopLocator, getWantsXorSizing()));
		v.addElement(new CpSizingHandle(this, CpBasicLocator.leftTopLocator, CpBasicLocator.rightBottomLocator, getWantsXorSizing()));
		v.addElement(new CpSizingHandle(this, CpBasicLocator.leftBottomLocator, CpBasicLocator.rightTopLocator, getWantsXorSizing()));
		v.addElement(new CpSizingHandle(this, CpBasicLocator.rightTopLocator, CpBasicLocator.leftBottomLocator, getWantsXorSizing()));
	    CpDependentLineLc connectionLine = new CpDependentLineLc();
	    connectionLine.endDecoration = connectionLine.ARROW;
 		v.addElement(new CpConnectingHandle(this, CpBasicLocator.rightMiddleLocator, new CpDependentConnector(connectionLine, false, false), new CpConnectionPolicy()));
		return v;
	}

	public boolean getWantsXorSizing()
	{
	    return false;
	}


	public CpHandle getDefaultHandle()
	{
	    return new CpMovingHandle(this, null);
	}

	public void drawHandles(Graphics g, boolean first)
	{
	    Vector handles = getHandles();
	    for (int i = 0; i < handles.size(); i++) {
	        ((CpHandle)handles.elementAt(i)).paint(g, first);
	    }
	}


	public boolean canBeSelected()
	{
   	    return true;
	}

	public Rectangle boundsDiagram()
	{
	    if (diagram == null) {
	        return boundsGlobal();
	    }
	    return new Rectangle(locationGlobal().x - diagram.locationGlobal().x, locationGlobal().y - diagram.locationGlobal().y, size().width, size().height);
	}

	public boolean insideDiagram(int x, int y)
	{
	    return insideGlobal(x + diagram.locationGlobal().x, y + diagram.locationGlobal().y);
	}

    public Vector getProperties()
    {
        if (properties == null) {
            properties = new Vector();
            properties.addElement(new CpProperty("Backcolor", CpBasicType.COLOR, BACKGROUND_PROP));
            Vector fonts = new Vector();
            fonts.addElement("Helvetica");
            fonts.addElement("Dialog");
            fonts.addElement("Courier");
            fonts.addElement("TimesRoman");
            properties.addElement(new CpProperty("Font Name", new CpChoiceType(fonts), FONTNAME_PROP));
        }
        return properties;
    }

    public Object getProperty(CpProperty prop)
    {
        switch (prop.getId()) {
            case BACKGROUND_PROP : return getBackground();
            case FONTNAME_PROP : return getFont().getName();
        }
        return null;
    }

    public void setProperty(CpProperty prop, Object o)
    {
        switch (prop.getId()) {
            case BACKGROUND_PROP : setBackground((Color)o); break;
            case FONTNAME_PROP : setFont(new Font((String)o, getFont().getStyle(), getFont().getSize())); break;
        }
    }
    public void move(int x, int y)
    {
        super.move(x, y);
        notifyObservers(LC_MOVED);
    }

    public void resize(int w, int h)
    {
        super.resize(w, h);
        notifyObservers(LC_SIZED);
    }


	public Dimension getConnectionOverlap()
	{
	    return new Dimension(0, 0);
	}

	public boolean getConnectionLinesFromCenterX()
	{
	    return false;
	}

	public boolean getConnectionLinesFromCenterY()
	{
	    return false;
	}

	// Convenience method
/*	public void setParameter(int parameter, Object arg1, Object arg2, boolean repairDamage)
	{
	    Vector args = new Vector(2);
	    args.addElement(arg1);
	    args.addElement(arg2);
	    setParameter(parameter, args, repairDamage);
	}

	public Object getParameter(int parameter)
	{
        switch (parameter) {
            case BOUNDS : {
                return bounds();
            }
            case LOCATION : {
                return location();
            }
        }
	    return null;
	}

    public void basicSetParameter(int parameter, Object value)
	{
	    switch (parameter) {
	        case BOUNDS : {
	            // hmmm... this probably should do a reshape, so that children coords are updated and layout is called.  But
	                // then reshape will cause a repair damage.  Probably dust all this and make properties specific to diagrammables, and handle moving/sizing separately
	            reshape((Rectangle)value);
	            break;
	        }
	        case LOCATION : {
	            move((Point)value);
	            break;
	        }
	        case RELATIVE_LOCATION : {
	            move(new Point(location().x + ((Point)value).x, location().y + ((Point)value).y));
	            break;
	        }
	    }
	}

	public void setParameter(int parameter, Object value, boolean repairDamage)
	{
	    Rectangle oldBoundingBox = bounds();
        basicSetParameter(parameter, value);
	    damage(oldBoundingBox);
	    damage(bounds());
	    notifyObservers(parameter, value);  // Should the parent be an observer or get an explicit notifyObservers?
            //	        this will notify parent (should this be explicity) which propogates up (WHY? who uses it? Oh, updating
	        //    size and move information on Diagram window.
            //	        this might notify dependentAdaptors which can check param and update accordingly,
	          //   damaging rects but not repairing.
	    if (repairDamage) {
	        repairDamage();
	    }
	}

	*/

}

