/*
 * JFieldPane.java  $Revision: 1.4 $  $Date: 2007/10/03 04:39:40 $
 *
 * Copyright (C) 2007 Meldcraft Corporation
 *
 * This file is part of Scaffold.
 * 
 * Scaffold is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Scaffold 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Scaffold.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.meldcraft.gui.swing;

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

import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;

/**
 * Panel that lays out rows of name/value components with aligned labels.
 *
 * @version $Revision: 1.4 $ $Date: 2007/10/03 04:39:40 $
 * @author rob
 */
public class JFieldPane extends JPanel
{
// Static variables
// Member variables
    private GridBagLayout       mGbag;
    private GridBagConstraints  mGbc;
    private Insets              mRequiredInsets = new Insets(5,0,0,0);
    private Insets              mLabelInsets = new Insets(5,0,0,12);
    private Insets              mCompInsets = new Insets(5,0,0,0);
    private String              mLabelSuffix;
    private boolean             mUseBoldLabels = false;
    private boolean             mExpandHorizontally = false;
    private boolean             mExpandVertically = false;
    private boolean             mComponentBeneath = false;
    private int                 mLabelOffset = 0;

// Constructors and initialization
    public JFieldPane()
    {
        this(null);
    }

    public JFieldPane(String labelSuffix)
    {
        this(labelSuffix, false);
    }

    public JFieldPane(String labelSuffix, boolean useBoldLabels)
    {
        mLabelSuffix = labelSuffix;
        mGbag = new GridBagLayout();
        mGbc = new GridBagConstraints();
        mGbc.fill = GridBagConstraints.HORIZONTAL;
        mGbc.anchor = GridBagConstraints.NORTHWEST;
        mGbc.weightx = 1;
        mGbc.weighty = 1;

        setLayout(mGbag);

        mUseBoldLabels = useBoldLabels;

        JTextField tf = new JTextField();
        JLabel label = new JLabel("F");
        mLabelOffset = (tf.getPreferredSize().height -
                        label.getPreferredSize().height) / 2;
        mLabelInsets.top += mLabelOffset;
    }

// Interface implemenations
// Public methods
    /** Sets whether subsequently added items are expanded horizontally. */
    public void setExpandHorizontally(boolean expand)
    {
        mExpandHorizontally = expand;
    }

    /** Sets whether subsequently added items are expanded vertically. */
    public void setExpandVertically(boolean expand)
    {
        mExpandVertically = expand;
    }

    /** Sets whether subsequently added components are beneath the label. */
    public void setComponentBeneath(boolean beneath)
    {
        mComponentBeneath = beneath;
    }

    /** Add the labeled component. */
    public void addRow(String label, Component c)
    {
        addRow(label, c, false);
    }

    /** Add the labeled component. */
    public void addRow(String label, Component c, boolean isRequired)
    {
        mGbc.gridy++;
        mGbc.gridwidth = 1;

        // add required moniker
        if (isRequired)
        {
            JLabel lab = new JLabel("*");
            mGbc.fill = GridBagConstraints.HORIZONTAL;
            mGbc.anchor = GridBagConstraints.WEST;
            mGbc.weightx = 0;
            mGbc.weighty = 0;
            mGbc.gridx = 0;
            mGbc.insets = mRequiredInsets;
            if (mGbc.gridy == 0)
            {
                mGbc.insets = new Insets(mLabelOffset, mRequiredInsets.left,
                                         mRequiredInsets.bottom,
                                         mRequiredInsets.right);
            }
            mGbag.setConstraints(lab, mGbc);
            add(lab);
        }

        // add label
        if (label != null)
        {
            if (mLabelSuffix != null)
            {
                label += mLabelSuffix;
            }
            JLabel lab = new JLabel(label);
            lab.setLabelFor(c);
            if (hasBoldLabels())
            {
                Font boldFont = lab.getFont().deriveFont(Font.BOLD);
                lab.setFont(boldFont);
            }

            mGbc.fill = GridBagConstraints.HORIZONTAL;
            mGbc.anchor = GridBagConstraints.NORTHWEST;
            mGbc.weightx = 0;
            mGbc.weighty = 0;
            mGbc.gridx = 1;
            mGbc.insets = mLabelInsets;
            if (mGbc.gridy == 0)
            {
                mGbc.insets = new Insets(mLabelOffset, mLabelInsets.left,
                                    mLabelInsets.bottom, mLabelInsets.right);
            }
            mGbag.setConstraints(lab, mGbc);
            add(lab);
        }

        // add component 
        mGbc.anchor = GridBagConstraints.NORTHWEST;
        mGbc.fill = mExpandHorizontally ? GridBagConstraints.BOTH : GridBagConstraints.NONE;
        mGbc.gridx = 2;
        mGbc.weightx = mExpandHorizontally ? 1 : 0;
        mGbc.weighty = mExpandVertically ? 1 : 0;
        mGbc.insets = mCompInsets;
        if (mGbc.gridy == 0)
        {
            mGbc.insets = new Insets(0, mCompInsets.left,
                                     mCompInsets.bottom, mCompInsets.right);
        }

        if (mComponentBeneath)
        {
            mGbc.gridy++;
            mGbc.gridx = 1;
            mGbc.gridwidth = GridBagConstraints.REMAINDER;
        }

        if (c != null)
        {
            mGbag.setConstraints(c, mGbc);
            add(c);
        }
    }

// Protected methods
    protected boolean hasBoldLabels()
    {
        return mUseBoldLabels;
    }

// Private methods
// Inner classes
}

