/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.ctecinf.swing;

import br.com.ctecinf.table.Table;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.border.TitledBorder;

/**
 *
 * @author Cássio Conceição
 * @since 11/06/2019
 * @version 1906
 * @see http://ctecinf.com.br/
 */
public class GridPanel extends JPanel {

    private int numColumns = 1;
    private int row = 1;

    public GridPanel() {
        this(1);
    }

    public GridPanel(int numColumns) {
        super(new GridBagLayout());
        this.numColumns = numColumns;
        this.row = 0;
    }

    public int getNumColumns() {
        return numColumns;
    }

    public int getRow() {
        return row;
    }

    public void newRow() {
        this.row++;
    }

    public JPanel add(JComponent component, int column) {
        return add(component, column, 1, !component.getClass().isAssignableFrom(JComboBox.class) && !component.getClass().isAssignableFrom(JCheckBox.class));
    }

    public JPanel add(JComponent component, int column, boolean fill) {
        return add(component, column, 1, fill);
    }

    public JPanel add(JComponent component, int column, int colsNumOccupped) {
        return add(component, column, colsNumOccupped, !component.getClass().isAssignableFrom(JComboBox.class) && !component.getClass().isAssignableFrom(JCheckBox.class));
    }

    public JPanel add(JComponent component, int column, int colsNumOccupped, boolean fill) {
        return add(component, column, row, colsNumOccupped, 1.00 / numColumns, fill);
    }

    public JPanel add(JComponent component, int gridx, int gridy, int gridwidth, double weightX, boolean fill) {
        return GridPanel.addComponent(this, component, gridx, gridy, gridwidth, weightX, fill);
    }

    public void end() {

        newRow();

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridy = row;
        gbc.gridx = 1;
        gbc.gridwidth = numColumns;
        gbc.weightx = 1.00;
        gbc.weighty = 1.00;

        add(new JPanel(), gbc);
    }

    public void setEnterForward(boolean b) {
        if (b) {
            Set forwardKeys = getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
            Set newForwardKeys = new HashSet(forwardKeys);
            newForwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
            setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newForwardKeys);
        }
    }

    /**
     * Adiciona um componente numa 'panel'
     *
     * @param panel JPanel para adicionar componente
     * @param component Componente a adicionar
     * @param gridx Coluna
     * @param gridy Linha
     * @param gridwidth Numero de colunas que o componente ocupa na linha
     *
     * @return JPanel
     */
    public static JPanel addComponent(JPanel panel, JComponent component, int gridx, int gridy, int gridwidth) {
        return addComponent(panel, component, gridx, gridy, gridwidth, GridBagConstraints.BOTH, true);
    }

    /**
     * Adiciona um componente numa 'panel'
     *
     * @param panel JPanel para adicionar componente
     * @param component Componente a adicionar
     * @param gridx Coluna
     * @param gridy Linha
     * @param gridwidth Numero de colunas que o componente ocupa na linha
     * @param fill Se componente preenche toda a coluna
     *
     * @return JPanel
     */
    public static final JPanel addComponent(JPanel panel, JComponent component, int gridx, int gridy, int gridwidth, boolean fill) {
        return addComponent(panel, component, gridx, gridy, gridwidth, GridBagConstraints.BOTH, fill);
    }

    /**
     * Adiciona um componente numa 'panel'
     *
     * @param panel JPanel para adicionar componente
     * @param component Componente a adicionar
     * @param gridx Coluna
     * @param gridy Linha
     * @param gridwidth Numero de colunas que o componente ocupa na linha
     * @param weightX Tamanho da coluna
     * @param fill Se componente preenche toda a coluna
     *
     * @return JPanel
     */
    public static final JPanel addComponent(JPanel panel, JComponent component, int gridx, int gridy, int gridwidth, double weightX, boolean fill) {

        if (panel == null) {
            panel = new JPanel(new GridBagLayout());
        }

        if (component == null) {
            return panel;
        }

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = fill ? GridBagConstraints.HORIZONTAL : GridBagConstraints.NONE;
        gbc.gridy = gridy;
        gbc.gridx = gridx;
        gbc.gridwidth = gridwidth;
        gbc.weightx = weightX;

        if (component.getClass().isAssignableFrom(Table.class)
                || component.getClass().isAssignableFrom(JTable.class)
                || component.getClass().isAssignableFrom(JList.class)
                || component.getClass().isAssignableFrom(JTextArea.class)
                || component.getClass().isAssignableFrom(JEditorPane.class)
                || component.getClass().isAssignableFrom(JTextPane.class)) {

            JScrollPane scroll;

            if (component.getClass().isAssignableFrom(Table.class)
                    || component.getClass().isAssignableFrom(JTable.class)
                    || component.getClass().isAssignableFrom(JList.class)) {

                scroll = new JScrollPane(component) {

                    private final Dimension d = new Dimension(300, 180);

                    @Override
                    public Dimension getPreferredSize() {
                        return d;
                    }
                };

            } else {
                scroll = new JScrollPane(component);
            }

            if (component.getBorder().getClass().isAssignableFrom(TitledBorder.class)) {
                scroll.setBorder(component.getBorder());
                component.setBorder(BorderFactory.createEtchedBorder());
            }

            panel.add(scroll, gbc);

        } else {
            panel.add(component, gbc);
        }

        return panel;
    }
}
