package speiger.src.ui;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;

public class VerticalFlowLayout implements LayoutManager, java.io.Serializable {

    private static final long serialVersionUID = -2732129344472207193L;

	/**
     * This value indicates that each row of components
     * should be left-justified.
     */
    public static final int TOP = 0;

    /**
     * This value indicates that each row of components
     * should be centered.
     */
    public static final int CENTER = 1;

    /**
     * This value indicates that each row of components
     * should be right-justified.
     */
    public static final int BOTTOM = 2;

    int align;
    protected int hgap;
    protected int vgap;

    /**
     * Constructs a new <code>FlowLayout</code> with a centered alignment and a
     * default 5-unit horizontal and vertical gap.
     */
    public VerticalFlowLayout() {
        this(CENTER, 5, 5);
    }
    
    public VerticalFlowLayout(int align) {
        this(align, 5, 5);
    }
    
    public VerticalFlowLayout(int align, int hgap, int vgap) {
        this.hgap = hgap;
        this.vgap = vgap;
        setAlignment(align);
    }
    
    public int getAlignment() { return align; }
    public void setAlignment(int align) { this.align = align; }
    public int getHgap() { return hgap; }
    public void setHgap(int hgap) { this.hgap = hgap; }
    public int getVgap() { return vgap; }
    public void setVgap(int vgap) { this.vgap = vgap; }

    public void addLayoutComponent(String name, Component comp) {}

    public void removeLayoutComponent(Component comp) {}
    
    public Dimension preferredLayoutSize(Container target) {
        synchronized (target.getTreeLock()) {
            Dimension dim = new Dimension(0, 0);
            int nmembers = target.getComponentCount();
            Boolean firstVisibleComponent = true;

            for (int i = 0; i < nmembers; i++) {
                Component m = target.getComponent(i);
                if (m.isVisible()) {
                    Dimension d = m.getPreferredSize();
                	dim.width = Math.max(dim.width, d.width);
                    if (firstVisibleComponent) {
                        firstVisibleComponent = false;
                    } else {
                        dim.height += vgap;
                    }

                    dim.height += d.height;
                }
            }
            Insets insets = target.getInsets();
            dim.width += insets.left + insets.right + hgap * 2;
            dim.height += insets.top + insets.bottom + vgap * 2;
            return dim;
        }
    }
    
    public Dimension minimumLayoutSize(Container target) {
        synchronized (target.getTreeLock()) {
            Dimension dim = new Dimension(0, 0);
            int nmembers = target.getComponentCount();
            
            for (int i = 0; i < nmembers; i++) {
                Component m = target.getComponent(i);
                if (m.isVisible()) {
                    Dimension d = m.getMinimumSize();
                	dim.width = Math.max(dim.width, d.width);
                    if (i > 0) {
                        dim.height += vgap;
                    }
                    dim.height += d.height;
                }
            }
            Insets insets = target.getInsets();
            dim.width += insets.left + insets.right + hgap * 2;
            dim.height += insets.top + insets.bottom + vgap * 2;
            return dim;
        }
    }
    
    private void moveComponents(Container target, int x, int y, int width, int height,
                                int rowStart, int rowEnd, boolean ltr) {
        synchronized (target.getTreeLock()) {
            switch (align) {
                case TOP:
                    y += ltr ? 0 : height;
                    break;
                case CENTER:
                    y += height / 2;
                    break;
                case BOTTOM:
                    y += ltr ? height : 0;
                    break;
            }
            for (int i = rowStart; i < rowEnd; i++) {
                Component m = target.getComponent(i);
                if (m.isVisible()) {
                    if (ltr) {
                        m.setLocation(x, y);
                    } else {
                        m.setLocation(x, target.getHeight() - y - m.getHeight());
                    }
                    y += m.getHeight() + vgap;
                }
            }
        }
    }
    
    public void layoutContainer(Container target) {
        synchronized (target.getTreeLock()) {
            Insets insets = target.getInsets();

            int maxlen = target.getHeight() - (insets.top + insets.bottom + vgap * 2);
            int nmembers = target.getComponentCount();
            int x = insets.left + hgap, y = 0;
            int roww = 0, start = 0;

            boolean ltr = target.getComponentOrientation().isLeftToRight();
            for (int i = 0; i < nmembers; i++) {
                Component m = target.getComponent(i);
                if (m.isVisible()) {
                    Dimension d = m.getPreferredSize();
                    m.setSize(d.width, d.height);
                	if ((y == 0) || ((y + d.height) <= maxlen)) {
                        if (y > 0) y += vgap;
                        y += d.height;
                        roww = Math.max(roww, d.width);
                    } else {
                        moveComponents(target, x, insets.top + vgap, roww, maxlen - y, start, i, ltr);
                        y = d.height;
                        x += hgap + roww;
                        roww = d.width;
                        start = i;
                    }
                }
            }
            
            moveComponents(target, x, insets.top + vgap, roww, maxlen - y, start, nmembers, ltr);
        }
    }
}