package cnp.ew.properties;

import java.awt.*;
import java.util.*;

import cnp.ew.scrolling.*;
import cnp.ew.util.*;
import cnp.ew.lightweight.*;
import cnp.ew.displayer.*;
import cnp.ew.converter.*;
import cnp.ew.text.*;
import cnp.ew.list.*;
import cnp.ew.button.*;

public class CpPropertySheet extends CpAbstractScrollable implements CpObserver
{
    Vector properties, labels, editors;
    CpHasProperties model;
    int cellHeight;

    static CpEdgeBorderDisplayer labelBorderDisplayer, editorBorderDisplayer;

    static {
        labelBorderDisplayer = new CpEdgeBorderDisplayer(0, 0, 1, 1);
        labelBorderDisplayer.borderColor = Color.lightGray;
        editorBorderDisplayer = new CpEdgeBorderDisplayer(0, 0, 0, 1);
        editorBorderDisplayer.borderColor = Color.lightGray;
    }

    public CpPropertySheet()
    {
        super();
        setBorderStyle(BORDER_INWARD3D);
    }

    public void setPropertiesAndModel(Vector v, CpHasProperties newModel)
    {
        // If we already have the right editors, check if the model has changed, and if so, fill in the new values
        if (properties == v) {
            if (model != newModel) {
                model = newModel;
                enableDamageRepair(false);
                for (int i = 0; i < editors.size(); i++) {
                    CpProperty prop = (CpProperty)properties.elementAt(i);
                    ((CpEditor)editors.elementAt(i)).setObject(model.getProperty(prop));
                }
                enableDamageRepair(true);
                repairDamage();
            }
            return;
        }
        model = newModel;
        enableDamageRepair(false);
        if (labels != null) {
            remove(labels);
            remove(editors);
        }
        properties = v;
        labels = new Vector();
        editors = new Vector();
        cellHeight = 0;
        for (int i = 0; i < properties.size(); i++) {
            CpProperty prop = (CpProperty)properties.elementAt(i);
            CpReadOnlyTextAreaLc label = new CpReadOnlyTextAreaLc(prop.getTitle());
            label.setBorderMargin(3, 0);
            label.setVerticalAlignment(label.ALIGN_CENTER);
            label.setBorderDisplayer(labelBorderDisplayer);
            add(label);
            labels.addElement(label);

            CpEditor editor = prop.getType().getDefaultEditor();
            editor.setVerticalAlignment(label.ALIGN_CENTER);
            editor.setIsTabStop(true);
            editor.setBorderDisplayer(editorBorderDisplayer);
            cellHeight = Math.max(cellHeight, editor.preferredSize().height);
            editor.setObject(model.getProperty(prop));
            editor.addObserver(this);
            add(editor);
            editors.addElement(editor);
        }
        layout();
        enableDamageRepair(true);
        repaint();
    }

    public void update(CpObservable o, int facet, Object arg)
    {
        switch (facet) {
            case CpEvent.OBJECT_CHANGING : {
                CpProperty prop = (CpProperty)properties.elementAt(editors.indexOf(o));
                model.setProperty(prop, ((CpEditor)o).getObject());
                break;
            }
        }
    }

    public void layout()
    {
        Rectangle client = getClientRect();
        int halfWidth = client.width / 2;
        int cellHeight = getCellSize().height;

        int curY = client.y;
        for (int i = 0; i < labels.size(); i++) {
            CpLightweightComponent c = (CpLightweightComponent)labels.elementAt(i);
            c.reshape(client.x, curY, halfWidth, cellHeight);

            c = (CpLightweightComponent)editors.elementAt(i);
            c.reshape(client.x + halfWidth, curY, halfWidth, cellHeight);
            curY += cellHeight;
        }
    }

    public void paint(Graphics g, Rectangle clip)
    {
        g.setColor(getBackground());
        g.fillRect(0, 0, size().width, size().height);
    }

    /***************** SCROLLING  ********************/

    public Dimension getCellSize()
    {
        return new Dimension(50, cellHeight);
    }

    public int getWidth()
    {
        return getVisibleRect().width;
    }

    public void scrollerSized(Dimension newSize)
    {
        recomputeSize();
    }

    void recomputeSize()
    {
        Dimension newSize = new Dimension(getWidth(), properties.size() * getCellSize().height);
        if (newSize.height != size().height || newSize.width != size().width) {
            resize(newSize);
            getScroller().scrollableSized();
        }
    }
}
