/*
Copyright (C) 2006 EBI
This library 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 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the itmplied 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 this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.biomart.builder.view.gui.dialogs;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicArrowButton;
import org.biomart.builder.model.Column;
import org.biomart.builder.model.Table;
import org.biomart.common.resources.Resources;
/**
* A dialog which lists all the columns in a key, and all the columns in the
* table which are available to put in that key. It can then allow the user to
* move those columns around, thus editing the key.
*
* @author Richard Holland <holland@ebi.ac.uk>
* @version $Revision: 1.11 $, $Date: 2007-09-10 12:29:36 $, modified by
* $Author: rh4 $
* @since 0.5
*/
public class KeyDialog extends JDialog {
private static final long serialVersionUID = 1;
private DefaultListModel selectedColumns;
private DefaultListModel tableColumns;
/**
* Pop up a dialog to define or edit a key.
*
* @param table
* the table the key belongs to.
* @param title
* the title to give the dialog.
* @param action
* the text to put on the OK button.
* @param columns
* the columns to preselect as part of the key.
*/
public KeyDialog(final Table table, final String title,
final String action, final Column[] columns) {
// Create the base dialog.
super();
this.setTitle(title);
this.setModal(true);
// The list of table columns is populated with the names of columns.
this.tableColumns = new DefaultListModel();
for (final Iterator i = new TreeSet(table.getColumns().values())
.iterator(); i.hasNext();)
this.tableColumns.addElement(i.next());
// The list of selected columns is populated with the columns from
// the existing key. These are also removed from the list of table
// columns, to prevent duplication.
this.selectedColumns = new DefaultListModel();
if (columns != null)
for (int i = 0; i < columns.length; i++) {
this.tableColumns.removeElement(columns[i]);
this.selectedColumns.addElement(columns[i]);
}
// The close and execute buttons.
final JButton close = new JButton(Resources.get("closeButton"));
final JButton execute = new JButton(action);
// Create the table column list, and the buttons
// to move columns to/from the selected column list.
final JList tabColList = new JList(this.tableColumns);
final JButton insertButton = new BasicArrowButton(SwingConstants.EAST);
final JButton removeButton = new BasicArrowButton(SwingConstants.WEST);
// Create the key column list, and the buttons to
// move columns to/from the table columns list.
final JList keyColList = new JList(this.selectedColumns);
final JButton upButton = new BasicArrowButton(SwingConstants.NORTH);
final JButton downButton = new BasicArrowButton(SwingConstants.SOUTH);
// Put the two halves of the dialog side-by-side in a horizontal box.
final Box content = Box.createHorizontalBox();
this.setContentPane(content);
// Left-hand side goes the table columns that are unused.
final JPanel leftPanel = new JPanel(new BorderLayout());
// Label at the top.
leftPanel.add(new JLabel(Resources.get("columnsAvailableLabel")),
BorderLayout.PAGE_START);
// Table columns list in the middle.
leftPanel.add(new JScrollPane(tabColList), BorderLayout.CENTER);
leftPanel.setBorder(new EmptyBorder(2, 2, 2, 2));
// Buttons down the right-hand-side, vertically.
final Box leftButtonPanel = Box.createVerticalBox();
leftButtonPanel.add(insertButton);
leftButtonPanel.add(removeButton);
leftButtonPanel.setBorder(new EmptyBorder(2, 2, 2, 2));
leftPanel.add(leftButtonPanel, BorderLayout.LINE_END);
content.add(leftPanel);
// Right-hand side goes the key columns that are used.
final JPanel rightPanel = new JPanel(new BorderLayout());
// Label at the top.
rightPanel.add(new JLabel(Resources.get("keyColumnsLabel")),
BorderLayout.PAGE_START);
// Key columns in the middle.
rightPanel.add(new JScrollPane(keyColList), BorderLayout.CENTER);
rightPanel.setBorder(new EmptyBorder(2, 2, 2, 2));
// Buttons down the right-hand-side, vertically.
final Box rightButtonPanel = Box.createVerticalBox();
rightButtonPanel.add(upButton);
rightButtonPanel.add(downButton);
rightButtonPanel.setBorder(new EmptyBorder(2, 2, 2, 2));
rightPanel.add(rightButtonPanel, BorderLayout.LINE_END);
// Close/Execute buttons at the bottom.
final Box actionButtons = Box.createHorizontalBox();
actionButtons.add(close);
actionButtons.add(execute);
actionButtons.setBorder(new EmptyBorder(2, 2, 2, 2));
rightPanel.add(actionButtons, BorderLayout.PAGE_END);
content.add(rightPanel);
// Intercept the insert/remove buttons
insertButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final Object selected = tabColList.getSelectedValue();
if (selected != null) {
// Move a column from table to key.
KeyDialog.this.selectedColumns.addElement(selected);
KeyDialog.this.tableColumns.removeElement(selected);
}
}
});
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final Object selected = keyColList.getSelectedValue();
if (selected != null) {
// Move a column from key to table.
KeyDialog.this.tableColumns.addElement(selected);
KeyDialog.this.selectedColumns.removeElement(selected);
}
}
});
// Intercept the up/down buttons
upButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final Object selected = keyColList.getSelectedValue();
if (selected != null) {
final int currIndex = KeyDialog.this.selectedColumns
.indexOf(selected);
if (currIndex > 0) {
// Swap the selected item with the one above it.
final Object swap = KeyDialog.this.selectedColumns
.get(currIndex - 1);
KeyDialog.this.selectedColumns.setElementAt(selected,
currIndex - 1);
KeyDialog.this.selectedColumns.setElementAt(swap,
currIndex);
// Select the selected item again, as it will
// have moved.
keyColList.setSelectedIndex(currIndex - 1);
}
}
}
});
downButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final Object selected = keyColList.getSelectedValue();
if (selected != null) {
final int currIndex = KeyDialog.this.selectedColumns
.indexOf(selected);
if (currIndex < KeyDialog.this.selectedColumns.size() - 1) {
// Swap the selected item with the one below it.
final Object swap = KeyDialog.this.selectedColumns
.get(currIndex + 1);
KeyDialog.this.selectedColumns.setElementAt(selected,
currIndex + 1);
KeyDialog.this.selectedColumns.setElementAt(swap,
currIndex);
// Select the selected item again, as it will
// have moved.
keyColList.setSelectedIndex(currIndex + 1);
}
}
}
});
// Intercept the close button, which closes the dialog
// without taking any action.
close.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
KeyDialog.this.setVisible(false);
}
});
// Intercept the execute button, which validates the fields
// then closes the dialog.
execute.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (KeyDialog.this.validateFields())
KeyDialog.this.setVisible(false);
}
});
// Make execute the default button.
this.getRootPane().setDefaultButton(execute);
// Set size of window.
this.pack();
// Move ourselves.
this.setLocationRelativeTo(null);
}
private boolean validateFields() {
// List of messages to display, if any are necessary.
final List messages = new ArrayList();
// Must have at least one column selected.
if (this.selectedColumns.isEmpty())
messages.add(Resources.get("keyColumnsEmpty"));
// Any messages to display? Show them.
if (!messages.isEmpty())
JOptionPane.showMessageDialog(null,
messages.toArray(new String[0]), Resources
.get("validationTitle"),
JOptionPane.INFORMATION_MESSAGE);
// Validation succeeds if there are no messages.
return messages.isEmpty();
}
/**
* Get the columns the user chose.
*
* @return the columns the user selected, in order.
*/
public Column[] getSelectedColumns() {
// For some reason, can't cast Object[] to Column[].
final Object[] objs = this.selectedColumns.toArray();
final Column[] cols = new Column[objs.length];
for (int i = 0; i < objs.length; i++)
cols[i] = (Column) objs[i];
return cols;
}
}