/*
 * This file is part of muCommander, http://www.mucommander.com
 *
 * muCommander is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * muCommander is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package com.mucommander.commons.util.ui.layout;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.text.JTextComponent;


/**
 * XAlignedComponentPanel is a panel which makes life easier when having
 * to display several rows of label + text field.
 * <p>On each row, labels are right-aligned and text fields left-aligned,
 * looking something like this:<br>
 * <pre>
 *       Label1 [Component1]<br>
 * LongerLabel2 [Component2]<br>
 *       Label3 [Component3]<br>
 * </pre>
 *
 * <p>Vertical space between labels and components, and horizontal space between rows can both be specified.
 *
 * @author Maxence Bernard
 */
public class XAlignedComponentPanel extends JPanel {

    /** Gridbag layout constraints */
    private GridBagConstraints c;

    /** Number of pixels between labels and components */
    private int xSpace;

    /**
     * First component in this panel, which will be given the focus when focus is requested on this panel using
     * {@link #requestFocus()}.
     */
    private JComponent firstComponent;


    public final static int DEFAULT_XPACE = 5;


    /**
     * Creates an initially empty panel, using the default vertical space as defined by {@link #DEFAULT_XPACE} to
     * separate labels and components for all rows added later.
     */
    public XAlignedComponentPanel() {
        this(DEFAULT_XPACE);
    }


    /**
     * Creates an initially empty panel, using the given vertical space to separate labels and components for
     * all rows added later.
     *
     * @param xSpace number of pixels to be inserted between labels and components.
     */
    public XAlignedComponentPanel(int xSpace) {
        // Set grid bag layout
        setLayout(new GridBagLayout());

        setAlignmentX(LEFT_ALIGNMENT);

        // Number of pixels between labels and components
        this.xSpace = xSpace;

        // Init gridbag constraints.
        this.c = new GridBagConstraints();
        this.c.anchor = GridBagConstraints.EAST;
    }

    public void setLabelLeftAligned(boolean aligned) {
        this.c.anchor = aligned ? GridBagConstraints.WEST : GridBagConstraints.EAST;
    }

    /**
     * Adds a new row with the given label and component, the component taking all the horizontal space left
     * by the widest label in this XAlignedComponentPanel.
     *
     * @param label text that describes the component
     * @param component JComponent instance, will take all remaining width space
     * @param ySpaceAfter number of pixels to be inserted after this row
     */
    public void addRow(String label, JComponent component, int ySpaceAfter) {
        addRow(new JLabel(label), component, ySpaceAfter);
    }


    /**
     * Adds a new row with the given label and component, the component taking all the horizontal space left
     * by the widest label in this XAlignedComponentPanel.
     *
     * @param label the label component that describes the component
     * @param component JComponent instance that will take all remaining width space
     * @param ySpaceAfter number of pixels to be inserted after this row
     */
    public void addRow(JComponent label, JComponent component, int ySpaceAfter) {
        if(firstComponent ==null)
            firstComponent = component;

        // Prepare grid bag constraints for label
        c.gridwidth = GridBagConstraints.RELATIVE;
        c.fill = GridBagConstraints.NONE;
        c.weightx = 0.0;
        c.insets = new Insets(0, 0, ySpaceAfter, xSpace);

        add(label, c);

        // Prepare grid bag constraints for component
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.insets = new Insets(0, 0, ySpaceAfter, 0);

        add(component, c);
    }


    /**
     * Adds a new row with the specified component left-aligned and taking all available width space.
     *
     * @param component JComponent instance that will take all available width space
     * @param ySpaceAfter number of pixels to be inserted after this row
     */
    public void addRow(JComponent component, int ySpaceAfter) {
        // Prepare grid bag constraints		
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.insets = new Insets(0, 0, ySpaceAfter, 0);

        add(component, c);
    }



    /**
     * Overrides JPanel#requestFocus() method to request focus on the first component
     * and select its contents if it is an instance of JTextComponent.
     */
    @Override
    public void requestFocus() {
        if(firstComponent ==null)
            super.requestFocus();
        else {
            if(firstComponent instanceof JTextComponent) {
                JTextComponent textComponent = (JTextComponent) firstComponent;
                String text = textComponent.getText();
                if(!text.equals("")) {
                    textComponent.setSelectionStart(0);
                    textComponent.setSelectionEnd(text.length());
                }
            }			
            firstComponent.requestFocus();
        }
    }
}
