/*******************************************************************************
* GenPlay, Einstein Genome Analyzer
* Copyright (C) 2009, 2014 Albert Einstein College of Medicine
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
* Authors: Julien Lajugie <julien.lajugie@einstein.yu.edu>
* Nicolas Fourel <nicolas.fourel@einstein.yu.edu>
* Eric Bouhassira <eric.bouhassira@einstein.yu.edu>
*
* Website: <http://genplay.einstein.yu.edu>
******************************************************************************/
package edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.vcfLoader;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFFile.VCFFile;
import edu.yu.einstein.genplay.util.Images;
import edu.yu.einstein.genplay.util.Utils;
/**
* This class is the VCF loader dialog.
* It displays a table for editing multi-genome VCF settings.
* Developer can:
* - show it
* - close it
* - set the data
* - get the data
* - check settings validity
*
* @author Nicolas Fourel
* @version 0.1
*/
public class VCFLoaderDialog extends JDialog {
/**
* Generated serial version ID
*/
private static final long serialVersionUID = -6703399045694111551L;
/** Return value when OK has been clicked. */
public static final int APPROVE_OPTION = 0;
/** Return value when Cancel has been clicked. */
public static final int CANCEL_OPTION = 1;
private static final String FONT_NAME = "ARIAL"; // name of the font
private static final int FONT_SIZE = 11; // size of the font
private static final int DIALOG_WIDTH = 700; // width of the dialog
private static final int VALIDATION_HEIGHT = 20; // height of the validation panel
private int approved = CANCEL_OPTION; // equals APPROVE_OPTION if user clicked OK, CANCEL_OPTION if not
private final Font font = new Font(FONT_NAME, Font.ITALIC, FONT_SIZE); // Font used in the dialog (How to use)
private final FontMetrics fm = getFontMetrics(font); // FontMetrics to get the size of a string
private final VCFLoaderTable table; // the table
/**
* Constructor of {@link VCFLoaderDialog}
*/
public VCFLoaderDialog () {
// Dimensions
Dimension dialogDim = new Dimension(DIALOG_WIDTH, 400);
Dimension validationDim = new Dimension(DIALOG_WIDTH, VALIDATION_HEIGHT);
// Table
VCFLoaderModel model = new VCFLoaderModel();
table = new VCFLoaderTable(model);
initializesPopUpMenu();
// Center
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.getVerticalScrollBar().setUnitIncrement(Utils.SCROLL_INCREMENT_UNIT);
table.setFillsViewportHeight(true);
// South
JPanel southPanel = getSouthPanel(validationDim);
// Dialog
setTitle("VCF Loader");
setSize(dialogDim);
setMinimumSize(new Dimension(getMinimumWidth(), getMinimumHeight()));
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(southPanel, BorderLayout.SOUTH);
setIconImages(Images.getApplicationImages());
}
/**
* Checks if row are valid.
* @return true if settings are valid, false otherwise
*/
public boolean areValidSettings () {
List<VCFData> data = getData();
String errors = "";
if ((data == null) || (data.size() == 0)) {
errors = "No settings found";
} else {
for (int i = 0; i < data.size(); i++) {
String error = data.get(i).getErrors();
if (error != null) {
errors += "row " + i + ": " + error +"\n";
}
}
}
if (errors.length() > 0) {
JOptionPane.showMessageDialog(this, errors, "Settings are not valid", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
/**
* Closes the VCF loader dialog
*/
public void closeDialog () {
setVisible(false);
}
/**
* @return the data
*/
public List<VCFData> getData() {
if (table != null) {
return table.getData();
}
return null;
}
/**
* Creates a square icon using the image
* @param image the image
* @return the icon
*/
private ImageIcon getIcon (Image image) {
return new ImageIcon(Images.getSquareImage(image, fm.getHeight()));
}
/**
* Information panel contains label about how to use the table
* @return the information panel
*/
private JPanel getInformationPanel () {
JPanel informationPanel = new JPanel();
GridBagLayout layout = new GridBagLayout();
informationPanel.setLayout(layout);
GridBagConstraints gbc = new GridBagConstraints();
JLabel label = new JLabel("Caption:");
label.setFont(font);
label.setOpaque(true);
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.insets = new Insets(0, 20, 0, 0);
informationPanel.add(label, gbc);
label = new JLabel("Add a new element to the list");
label.setIcon(getIcon(Images.getAddImage()));
label.setFont(font);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.insets = new Insets(0, 40, 0, 0);
informationPanel.add(label, gbc);
label = new JLabel("Edit the selected element");
label.setIcon(getIcon(Images.getEditImage()));
label.setFont(font);
gbc.gridx = 0;
gbc.gridy = 2;
informationPanel.add(label, gbc);
label = new JLabel("Delete the selected element");
label.setIcon(getIcon(Images.getDeleteImage()));
label.setFont(font);
gbc.gridx = 0;
gbc.gridy = 3;
informationPanel.add(label, gbc);
label = new JLabel("Add/Delete row(s)");
label.setIcon(getIcon(Images.getMouseImage()));
label.setFont(font);
gbc.gridx = 0;
gbc.gridy = 4;
informationPanel.add(label, gbc);
return informationPanel;
}
/**
* The minimum height is the height of the caption, the validation panel height plus 100
* @return the minimum height of the dialog
*/
private int getMinimumHeight () {
int height = VALIDATION_HEIGHT + (fm.getHeight() * 4) + 100;
return height;
}
/**
* The minimum width is according to the longest text label
* @return the minimum width of the dialog
*/
private int getMinimumWidth () {
int width = 250;
return width;
}
/**
* Initializes the south panel.
* South panel contains "how to use" panel and Ok/Cancel button panel.
* @param validationDimension
*/
private JPanel getSouthPanel (Dimension validationDimension) {
JPanel southPanel = new JPanel();
southPanel.setLayout(new BorderLayout());
southPanel.add(getInformationPanel(), BorderLayout.CENTER);
southPanel.add(getValidationPanel(validationDimension), BorderLayout.SOUTH);
return southPanel;
}
/**
* The validation panel contains ok and cancel buttons
* @param dimension dimension of the panel
* @return the panel
*/
private JPanel getValidationPanel (Dimension dimension) {
//Dimension buttonDim = new Dimension(60, 40);
Insets inset = new Insets(0, 0, 0, 0);
JButton confirm = new JButton("Ok");
confirm.setToolTipText("Ok");
confirm.setMargin(inset);
confirm.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
approved = APPROVE_OPTION;
closeDialog();
}
});
JButton cancel = new JButton("Cancel");
cancel.setToolTipText("Cancel");
cancel.setMargin(inset);
cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
approved = CANCEL_OPTION;
closeDialog();
}
});
confirm.setPreferredSize(cancel.getPreferredSize());
JPanel validationPanel = new JPanel();
validationPanel.add(confirm);
validationPanel.add(cancel);
validationPanel.setSize(dimension);
return validationPanel;
}
/**
* @param file
* @return the existing VCF file (if exists) or a new VCF File
*/
public VCFFile getVCFFile (File file) {
return table.getVCFFile(file);
}
/**
* Initializes the popup menu for the table.
*/
private void initializesPopUpMenu () {
MouseListener popupListener = new MouseAdapter() {
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
JPopupMenu popup = new JPopupMenu();
JMenuItem menuItem;
menuItem = new JMenuItem("Add row");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
table.addEmptyRow();
}
});
popup.add(menuItem);
menuItem = new JMenuItem("Delete selected row(s)");
if (table.getSelectedRowCount() == 0) {
menuItem.setEnabled(false);
} else {
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
int[] selectedRows = table.getSelectedRows();
int index = selectedRows.length;
int[] reverse = new int[index];
for (int i: selectedRows) {
index--;
reverse[index] = i;
}
for (int i: reverse) {
((VCFLoaderModel) table.getModel()).deleteRow(i);
}
}
});
}
popup.add(menuItem);
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
@Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
};
table.addMouseListener(popupListener);
}
/**
* @param data the data to set
*/
public void setData(List<VCFData> data) {
table.setData(data);
}
/**
* Shows the component.
* @param parent the parent component of the dialog, can be null; see showDialog for details
* @return APPROVE_OPTION is OK is clicked. CANCEL_OPTION otherwise.
*/
public int showDialog(Component parent) {
if (table.getData().size() == 0) {
table.addEmptyRow();
}
setModalityType(ModalityType.APPLICATION_MODAL);
setLocationRelativeTo(parent);
setVisible(true);
return approved;
}
}