/******************************************************************************* * 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.MGProperties.filterDialog.panels; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFHeaderType.VCFHeaderAdvancedType; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFHeaderType.VCFHeaderType; import edu.yu.einstein.genplay.core.multiGenome.filter.utils.FormatFilterOperatorType; import edu.yu.einstein.genplay.dataStructure.enums.VCFColumnName; /** * Panel to select genomes and operator. This panel is used when the VCF field of the filter is FORMAT. * The FORMAT field has different values for each genomes of the VCF file and the user needs to select * on which genomes he wants to apply the filter. * @author Julien Lajugie */ public class MultiGenomePanel extends JPanel implements ItemListener { /** Generated serial version ID */ private static final long serialVersionUID = -4060807866730514644L; /** Name of the property that is true when the selection in this panel is valid, false otherwise */ public static final String IS_SELECTION_VALID_PROPERTY_NAME = "Is selection valid"; private final JScrollPane genomeScroll; // scroll pane with the check boxes private final JComboBox operatorCombobox; // combo box to choose an operator private JCheckBox[] genomeBoxes; // check boxes to select genomes private boolean isSelectionValid; // true if the current selection is valid /** * Creates an instance of {@link MultiGenomePanel} * @param genomeNames name of the genomes displayed in the panel * @param selectedHeader VCF field currently being filtered * @param selectedGenomes list of the genomes preselected, can be null * @param selectedOperator operator preselected, can be null */ public MultiGenomePanel(List<String> genomeNames, VCFHeaderType selectedHeader, List<String> selectedGenomes, FormatFilterOperatorType selectedOperator) { super(new GridBagLayout()); setBorder(BorderFactory.createTitledBorder("Select Genome(s)")); // create the components JLabel jlGenome = new JLabel("Apply FORMAT filter on:"); genomeScroll = new JScrollPane(); setGenomeList(genomeNames, selectedGenomes); JLabel jlOperator = new JLabel("Using operator:"); operatorCombobox = new JComboBox(); operatorCombobox.setPrototypeDisplayValue("Mean"); setHeaderType(selectedHeader); if (selectedOperator != null) { operatorCombobox.setSelectedItem(selectedOperator); } checkIfGenomeComboEnabled(); // add the components GridBagConstraints gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.FIRST_LINE_START; gbc.weightx = 1; gbc.weighty = 1; add(jlGenome, gbc); gbc.gridy = 1; add(genomeScroll, gbc); gbc.gridy = 2; gbc.insets = new Insets(20, 0, 0, 0); add(jlOperator, gbc); gbc.fill = GridBagConstraints.NONE; gbc.gridy = 3; gbc.insets = new Insets(0, 10, 0, 0); gbc.weighty = 1; add(operatorCombobox, gbc); } /** * Enables the operator combo box if more than one genome is selected. \ * Disables it otherwise */ private void checkIfGenomeComboEnabled() { int selectedGenomeCount = 0; for (JCheckBox jcb: genomeBoxes) { if (jcb.isSelected()) { selectedGenomeCount++; } } operatorCombobox.setEnabled(selectedGenomeCount > 1); } /** * Checks if the current selection made by the user is valid and update the * {@link #isSelectionValid} property. Fire a property change event if the * property changes. */ private final void checkIfSelectionIsValid() { boolean newIsSelectionValid = false; for (int i = 0; (i < genomeBoxes.length) && !newIsSelectionValid; i++) { if (genomeBoxes[i].isSelected()) { newIsSelectionValid = true; } } if (newIsSelectionValid != isSelectionValid) { boolean oldIsSelectionValid = isSelectionValid; isSelectionValid = newIsSelectionValid; firePropertyChange(IS_SELECTION_VALID_PROPERTY_NAME, oldIsSelectionValid, newIsSelectionValid); } } /** * The list of the selected genomes */ public List<String> getSelectedGenomes() { List<String> resultList = new ArrayList<String>(); for (JCheckBox jcb: genomeBoxes) { if (jcb.isSelected()) { resultList.add(jcb.getText()); } } return resultList; } /** * @return the selected operator */ public FormatFilterOperatorType getSelectedOperator() { return (FormatFilterOperatorType) operatorCombobox.getSelectedItem(); } /** * @return true if the current selection is valid, false otherwise */ public boolean isSelectionValid() { return isSelectionValid; } @Override public void itemStateChanged(ItemEvent e) { checkIfSelectionIsValid(); checkIfGenomeComboEnabled(); } /** * Sets the list of genomes displayed in the panel * @param genomeNames list of genome names */ public void setGenomeList(List<String> genomeNames) { setGenomeList(genomeNames, null); } /** * Sets the list of genomes displayed in the panel. * The specified genomes are selected the others are unselected. * @param genomeNames list of genome names * @param selectedGenomes this genomes will be selected, other genomes will be unselected. Everything will be selected if null */ private void setGenomeList(List<String> genomeNames, List<String> selectedGenomes) { JPanel content = new JPanel(); content.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1; gbc.weighty = 1; genomeBoxes = new JCheckBox[genomeNames.size()]; for (int i = 0; i < genomeNames.size(); i++) { JCheckBox checkBox = new JCheckBox(genomeNames.get(i)); if (selectedGenomes != null) { checkBox.setSelected(selectedGenomes.contains(genomeNames.get(i))); } else { checkBox.setSelected(true); } checkBox.addItemListener(this); genomeBoxes[i] = checkBox; content.add(genomeBoxes[i], gbc); gbc.gridy++; } genomeScroll.setViewportView(content); if (genomeNames.size() <= 1) { setVisible(false); } checkIfSelectionIsValid(); } /** * Sets the VCF filed that is selected. The content of this panel will * adapt to the type of the field * @param vcfHeaderType a VCF field */ public void setHeaderType(VCFHeaderType vcfHeaderType) { if ((genomeBoxes.length <= 1) || (vcfHeaderType.getColumnCategory() != VCFColumnName.FORMAT)) { setVisible(false); } else { setVisible(true); operatorCombobox.removeAllItems(); if (vcfHeaderType instanceof VCFHeaderAdvancedType) { VCFHeaderAdvancedType advancedHeader = (VCFHeaderAdvancedType) vcfHeaderType; operatorCombobox.addItem(FormatFilterOperatorType.AND); operatorCombobox.addItem(FormatFilterOperatorType.OR); if ((advancedHeader.getType() == Integer.class) || (advancedHeader.getType() == Float.class)) { operatorCombobox.addItem(FormatFilterOperatorType.MEAN); operatorCombobox.addItem(FormatFilterOperatorType.SUM); } } } } }