edu.ku.brc.af.ui.forms.formatters.DataObjFieldFormatMultiplePanel.java Source code

Java tutorial

Introduction

Here is the source code for edu.ku.brc.af.ui.forms.formatters.DataObjFieldFormatMultiplePanel.java

Source

/* Copyright (C) 2015, University of Kansas Center for Research
 * 
 * Specify Software Project, specify@ku.edu, Biodiversity Institute,
 * 1345 Jayhawk Boulevard, Lawrence, Kansas, 66045, USA
 * 
 * This program 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 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package edu.ku.brc.af.ui.forms.formatters;

import static edu.ku.brc.ui.UIHelper.createButton;
import static edu.ku.brc.ui.UIHelper.createCheckBox;
import static edu.ku.brc.ui.UIRegistry.getResourceString;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

import org.apache.commons.lang.StringUtils;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import edu.ku.brc.af.core.db.DBTableInfo;
import edu.ku.brc.ui.CustomDialog;
import edu.ku.brc.ui.EditDeleteAddPanel;
import edu.ku.brc.ui.UIHelper;
import edu.ku.brc.ui.UIRegistry;

/**
 * 
 * @author Ricardo
 * @author rods
 *
 * @code_status Alpha
 *
 */
public class DataObjFieldFormatMultiplePanel extends DataObjFieldFormatPanel implements ChangeListener {

    protected static final String FIELD_VALUE_COL;
    protected static final String DISPLAY_FORMAT_COL;
    protected static final String ELLIPSIS_BUTTON_COL = "";

    protected final String ellipsisButtonLabel = "...";

    protected JTable formatSwitchTbl;
    protected EditDeleteAddPanel controlPanel;

    static {
        FIELD_VALUE_COL = getResourceString("DOF_FIELD_VALUE");
        DISPLAY_FORMAT_COL = getResourceString("DOF_DISPLAY_FORMAT");
    }

    /**
     * @param tableInfo
     * @param availableFieldsComp
     * @param formatContainer
     * @param okButton
     * @param uiFieldFormatterMgrCache
     */
    public DataObjFieldFormatMultiplePanel(final DBTableInfo tableInfo,
            final DataObjSwitchFormatterContainerIface formatContainer,
            final DataObjFieldFormatMgr dataObjFieldFormatMgrCache,
            final UIFieldFormatterMgr uiFieldFormatterMgrCache, final ChangeListener listener,
            final JButton okButton) {
        super(tableInfo, formatContainer, dataObjFieldFormatMgrCache, uiFieldFormatterMgrCache, listener, okButton);
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.formatters.DataObjFieldFormatPanelBuilder#buildUI()
     */
    protected void buildUI() {
        CellConstraints cc = new CellConstraints();
        PanelBuilder pb = new PanelBuilder(new FormLayout("f:p:g", "10px,f:130px:g,10px,p,15px"), this);

        formatSwitchTbl = new JTable(new DefaultTableModel());
        formatSwitchTbl.getSelectionModel().addListSelectionListener(new RowListener());
        addTableModelListener((DefaultTableModel) formatSwitchTbl.getModel());
        fillWithObjFormatter(null);

        // tool bar to host the add and delete buttons
        createToolbar();

        // lay out components on main panel
        JScrollPane sp = UIHelper.createScrollPane(formatSwitchTbl);
        // set minimum and preferred sizes so that table shrinks with the dialog
        sp.setMinimumSize(new Dimension(50, 5));
        sp.setPreferredSize(new Dimension(50, 5));

        pb.add(sp, cc.xy(1, 2));
        pb.add(controlPanel, cc.xy(1, 4));
        this.mainPanelBuilder = pb;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.formatters.DataObjFieldFormatPanelBuilder#enableUIControls()
     */
    public void enableUIControls() {
        okButton.setEnabled(!isInError());
        controlPanel.getDelBtn().setEnabled(formatSwitchTbl.getSelectedRowCount() > 0);
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.formatters.DataObjFieldFormatPanelBuilder#isInError()
     */
    @Override
    public boolean isInError() {
        return super.isInError() || !isValidFormatter();
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.formatters.DataObjFieldFormatPanelBuilder#getMainPanelBuilder()
     */
    public PanelBuilder getMainPanelBuilder() {
        return mainPanelBuilder;
    }

    /**
     * @param model
     */
    protected void addTableModelListener(DefaultTableModel model) {
        TableModelListener tml = new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                int row = e.getFirstRow();
                int column = e.getColumn();
                DefaultTableModel localModel = (DefaultTableModel) e.getSource();
                String columnName = localModel.getColumnName(column);

                if (columnName.equals(FIELD_VALUE_COL)) {
                    int formatColumn = formatSwitchTbl.getColumnModel().getColumnIndex(DISPLAY_FORMAT_COL);
                    DataObjDataFieldFormat format = (DataObjDataFieldFormat) localModel.getValueAt(row,
                            formatColumn);
                    String value = (String) localModel.getValueAt(row, column);
                    format.setValue(value);
                    enableUIControls();
                }
            }
        };
        model.addTableModelListener(tml);
    }

    /**
     * @return
     */
    protected boolean isValidFormatter() {
        // check if there's an empty row in the switch formatter table
        DefaultTableModel model = (DefaultTableModel) formatSwitchTbl.getModel();

        if (model.getRowCount() == 0) {
            return false; // formatter is not valid if there are no internal formatters attached to it
        }

        Set<String> valueSet = new HashSet<String>();
        // check if there are valid values in each row
        for (int i = 0; i < model.getRowCount(); ++i) {
            for (int j = 0; j <= 1; ++j) {
                Object obj = model.getValueAt(i, j);
                String value = obj.toString();
                if (obj == null || StringUtils.isEmpty(value)) {
                    return false;
                }
                // also check if field value is unique (column 0)
                if (j == 0) {
                    // value already in the set: so it's not unique
                    if (valueSet.contains(value))
                        return false;

                    valueSet.add(value);
                }
            }
        }
        return true;
    }

    /**
     * @return
     */
    private DefaultTableModel getCleanTableModel() {
        DefaultTableModel model = new DefaultTableModel() {
            public boolean isCellEditable(int row, int column) {
                return (column != 1);
            }
        };
        model.addColumn(FIELD_VALUE_COL);
        model.addColumn(DISPLAY_FORMAT_COL);
        model.addColumn(ELLIPSIS_BUTTON_COL);

        addTableModelListener(model);
        return model;
    }

    private void createToolbar() {
        ActionListener addAL = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                DefaultTableModel model = (DefaultTableModel) formatSwitchTbl.getModel();
                DataObjSwitchFormatter fmt = formatContainer.getSelectedFormatter();
                DataObjDataFieldFormat fld = new DataObjDataFieldFormat();
                fmt.add(fld);
                model.addRow(new Object[] { fld.getValue(), fld, ellipsisButtonLabel });
                setHasChanged(true);
                enableUIControls();
            }
        };

        ActionListener delAL = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int formatColumn = formatSwitchTbl.getColumn(DISPLAY_FORMAT_COL).getModelIndex();
                DefaultTableModel model = (DefaultTableModel) formatSwitchTbl.getModel();
                DataObjSwitchFormatter fmt = formatContainer.getSelectedFormatter();
                int[] rows = formatSwitchTbl.getSelectedRows();
                // sort rows in reverse order otherwise removing the first rows
                // will mess up with the row numbers
                Integer[] intRows = new Integer[rows.length];
                for (int i = 0; i < rows.length; ++i) {
                    intRows[i] = new Integer(rows[i]);
                }
                Arrays.sort(intRows, Collections.reverseOrder());
                for (int currentRow : intRows) {
                    fmt.remove((DataObjDataFieldFormatIFace) model.getValueAt(currentRow, formatColumn));
                    model.removeRow(currentRow);
                }
                formatSwitchTbl.clearSelection();
                setHasChanged(true);
                enableUIControls();
            }
        };

        controlPanel = new EditDeleteAddPanel(null, delAL, addAL);
        controlPanel.getAddBtn().setEnabled(true);
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.formatters.DataObjFieldFormatPanelBuilder#fillWithObjFormatter(edu.ku.brc.ui.forms.formatters.DataObjSwitchFormatter)
     */
    public void fillWithObjFormatter(final DataObjSwitchFormatter switchFormatter) {
        // display each formatter as a table row
        // DefaultTableModel tableModel = (DefaultTableModel)
        // formatSwitch.getModel();
        DefaultTableModel model = getCleanTableModel();

        if (switchFormatter != null) {
            Vector<DataObjDataFieldFormatIFace> formatters = new Vector<DataObjDataFieldFormatIFace>(
                    switchFormatter.getFormatters());
            for (DataObjDataFieldFormatIFace formatter : formatters) {
                model.addRow(new Object[] { formatter.getValue(), formatter, ellipsisButtonLabel });
            }
        }

        formatSwitchTbl.setModel(model);
        setFormatSwitchTblColumnProperties();
    }

    /**
     * 
     */
    private void setFormatSwitchTblColumnProperties() {
        // set details of 1st column (field values)
        TableColumnModel model = formatSwitchTbl.getColumnModel();
        TableColumn column = model.getColumn(model.getColumnIndex(FIELD_VALUE_COL));
        column.setMinWidth(20);
        column.setMaxWidth(300);
        column.setPreferredWidth(70);
        DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
        renderer.setHorizontalAlignment(SwingConstants.CENTER);
        column.setCellRenderer(renderer);

        // set details of 3rd column (ellipsis buttons)
        column = model.getColumn(model.getColumnIndex(ELLIPSIS_BUTTON_COL));
        column.setCellRenderer(new EditDataObjFormatButtonRenderer());
        column.setCellEditor(new EditDataObjFormatButtonEditor(createCheckBox()));
        column.setMinWidth(20);
        column.setMaxWidth(20);
        column.setPreferredWidth(20);
    }

    private class RowListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent event) {
            if (event.getValueIsAdjusting()) {
                return;
            }

            enableUIControls();
        }
    }

    /*
     * Table cell renderer that renders ellipsis button that opens format editor
     */
    protected class EditDataObjFormatButtonRenderer extends JButton implements TableCellRenderer {
        public EditDataObjFormatButtonRenderer() {
            setOpaque(true);
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            if (isSelected) {
                setForeground(table.getSelectionForeground());
                setBackground(table.getSelectionBackground());
            } else {
                setForeground(table.getForeground());
                setBackground(UIManager.getColor("Button.background"));
            }
            setText(ellipsisButtonLabel);
            return this;
        }
    }

    /*
     * Table cell editor that forwards events to rendered ellipsis buttons on
     * the table
     */
    protected class EditDataObjFormatButtonEditor extends DefaultCellEditor {
        protected JButton button;
        private boolean isPushed;
        private JTable table;
        private int row;

        public EditDataObjFormatButtonEditor(final JCheckBox checkBox) {
            super(checkBox);

            button = createButton();
            button.setOpaque(true);
            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    fireEditingStopped();
                }
            });
        }

        public Component getTableCellEditorComponent(JTable tableArg, Object value, boolean isSelected, int rowArg,
                int column) {
            if (isSelected) {
                button.setForeground(tableArg.getSelectionForeground());
                button.setBackground(tableArg.getSelectionBackground());
            } else {
                button.setForeground(tableArg.getForeground());
                button.setBackground(tableArg.getBackground());
            }
            button.setText(ellipsisButtonLabel);
            isPushed = true;

            this.table = tableArg;
            this.row = rowArg;

            return button;
        }

        public Object getCellEditorValue() {
            if (isPushed) {
                // get formatter object that corresponds to the pressed button
                int formatCol = table.getColumn(DISPLAY_FORMAT_COL).getModelIndex();
                Object fieldObj = table.getValueAt(row, formatCol);
                if (fieldObj instanceof DataObjDataFieldFormatIFace) {
                    DataObjDataFieldFormatIFace formatter = (DataObjDataFieldFormatIFace) fieldObj;

                    // open dialog to edit format
                    DataObjFieldFormatSingleDlg dlg = new DataObjFieldFormatSingleDlg(
                            (Frame) UIRegistry.getTopWindow(), tableInfo, formatter, dataObjFieldFormatMgrCache,
                            uiFieldFormatterMgrCache);
                    dlg.setVisible(true);

                    // save format back to table row data object
                    if (dlg.getBtnPressed() == CustomDialog.OK_BTN) {

                        DataObjSwitchFormatter fmt = formatContainer.getSelectedFormatter();
                        DataObjDataFieldFormatIFace field = dlg.getSingleFormatter();
                        fmt.set(row, field);
                        table.setValueAt(field, row, formatCol);

                        // get field value from table and assign it to newly created formatter
                        int valueCol = table.getColumn(FIELD_VALUE_COL).getModelIndex();
                        String value = (String) table.getValueAt(row, valueCol);
                        field.setValue(value);

                        setHasChanged(true);
                        // update ok button based on results
                        enableUIControls();
                    }
                }
            }
            isPushed = false;
            return new String(ellipsisButtonLabel);
        }

        public boolean stopCellEditing() {
            isPushed = false;
            return super.stopCellEditing();
        }

        protected void fireEditingStopped() {
            super.fireEditingStopped();
        }
    }

    /* (non-Javadoc)
     * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
     */
    public void stateChanged(ChangeEvent e) {
        listener.stateChanged(e);
    }

}