/******************************************************************************* * 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.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JPanel; import javax.swing.JRadioButton; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFHeaderType.VCFHeaderAdvancedType; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFHeaderType.VCFHeaderBasicType; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFHeaderType.VCFHeaderElementRecord; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFHeaderType.VCFHeaderFilterType; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFHeaderType.VCFHeaderType; import edu.yu.einstein.genplay.core.multiGenome.filter.FilterInterface; import edu.yu.einstein.genplay.core.multiGenome.filter.VCFID.GenotypeIDFilter; import edu.yu.einstein.genplay.core.multiGenome.filter.VCFID.IDFilterInterface; import edu.yu.einstein.genplay.dataStructure.enums.VCFColumnName; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.idEditors.IDEditor; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.idEditors.IDFlagEditor; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.idEditors.IDGTEditor; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.idEditors.IDNumberEditor; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.idEditors.IDStringEditor; /** * Panels to select values for a filter * @author Nicolas Fourel * @author Julien Lajugie */ public class FilterValuesPanel extends JPanel implements ActionListener, PropertyChangeListener { /** 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"; /** Generated serial version ID */ private static final long serialVersionUID = -5350638693635564694L; /** Preferred height of this panel */ private final int PREFERRED_HEIGHT = 180; private IDEditor filterEditor; // regular editor private IDEditor specialFilterEditor; // editor for GT field private JRadioButton regularRadioBox; // box to choose the regular editor to edit a GT field private JRadioButton specialRadioBox; // box to choose the special editor to edit a GT fied private boolean isSelectionValid; // return true if the current selection is valid, false otherwise /** * Constructor of {@link FilterValuesPanel} */ public FilterValuesPanel(VCFHeaderType headerType, FilterInterface filterInterface) { super(new GridBagLayout()); setBorder(BorderFactory.createTitledBorder("Select filter values")); setHeaderType(headerType); if (filterInterface != null) { initialize(filterInterface); } setPreferredSize(new Dimension(getPreferredSize().width, PREFERRED_HEIGHT)); } @Override public void actionPerformed(ActionEvent arg0) { if (arg0.getSource() instanceof JRadioButton) { JRadioButton radio = (JRadioButton) arg0.getSource(); if (radio.equals(regularRadioBox)) { specialFilterEditor.setVisible(false); filterEditor.setVisible(true); } else { filterEditor.setVisible(false); specialFilterEditor.setVisible(true); } checkIfSelectionIsValid(); } } /** * 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; if ((regularRadioBox == null) || !regularRadioBox.isVisible() || regularRadioBox.isSelected()) { newIsSelectionValid = filterEditor.isSelectionValid(); } else if (specialFilterEditor != null) { newIsSelectionValid = specialFilterEditor.isSelectionValid(); } if (newIsSelectionValid != isSelectionValid) { boolean oldIsSelectionValid = isSelectionValid; isSelectionValid = newIsSelectionValid; firePropertyChange(IS_SELECTION_VALID_PROPERTY_NAME, oldIsSelectionValid, newIsSelectionValid); } } /** * Creates the panel containing the editor. * If a special editor has been created (as for the GT field), it will be put on the top. * @return the panel containing the editor(s) */ private JPanel getCustomPanel () { JPanel panel = null; JPanel regularPanel = filterEditor.updatePanel(); regularPanel.addPropertyChangeListener(IDEditor.IS_SELECTION_VALID_PROPERTY_NAME, this); if (specialFilterEditor != null) { panel = new JPanel(); JPanel specialPanel = specialFilterEditor.updatePanel(); specialPanel.addPropertyChangeListener(IDEditor.IS_SELECTION_VALID_PROPERTY_NAME, this); regularRadioBox = new JRadioButton("<html><i>Regular Editor:</i><html>"); regularRadioBox.addActionListener(this); specialRadioBox = new JRadioButton("<html><i>Special Editor:</i><html>"); specialRadioBox.addActionListener(this); specialRadioBox.setSelected(true); // Creates the group ButtonGroup group = new ButtonGroup(); group.add(regularRadioBox); group.add(specialRadioBox); // Layout settings GridBagLayout layout = new GridBagLayout(); panel.setLayout(layout); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.FIRST_LINE_START; gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1; gbc.weighty = 1; panel.add(specialRadioBox, gbc); gbc.gridy++; gbc.insets = new Insets(0, 10, 0, 0); panel.add(specialPanel, gbc); specialFilterEditor.setVisible(true); gbc.gridy++; gbc.insets = new Insets(10, 0, 0, 0); panel.add(regularRadioBox, gbc); gbc.gridy++; gbc.insets = new Insets(0, 10, 0, 0); panel.add(regularPanel, gbc); filterEditor.setVisible(false); } else { panel = regularPanel; } return panel; } /** * @return the ID filter */ public FilterInterface getFilter () { if (filterEditor.isVisible()) { return filterEditor.getFilter(); } return specialFilterEditor.getFilter(); } /** * Initializes the editors. Select editors adapted to the VCF * field to edit. * @param headerType */ private void initEditors(VCFHeaderType headerType) { filterEditor = null; specialFilterEditor = null; if (headerType instanceof VCFHeaderBasicType) { VCFHeaderBasicType header = (VCFHeaderBasicType) headerType; VCFColumnName column = header.getColumnCategory(); if (column == VCFColumnName.ALT) { filterEditor = new IDStringEditor(); } else if (column == VCFColumnName.QUAL) { filterEditor = new IDNumberEditor(); } else if (column == VCFColumnName.FILTER) { filterEditor = new IDStringEditor(); if (header instanceof VCFHeaderElementRecord) { List<String> elements = new ArrayList<String>(); List<Object> elementsList = ((VCFHeaderElementRecord)header).getElements(); for (Object o: elementsList) { if ((elementsList != null) && (elementsList.size() > 0)) { if (o instanceof String) { elements.add(o.toString()); } else if (o instanceof VCFHeaderBasicType) { elements.add(((VCFHeaderBasicType)o).getId()); } } } ((IDStringEditor)filterEditor).setDefaultElements(elements); } } } else if (headerType instanceof VCFHeaderAdvancedType) { VCFHeaderAdvancedType advancedHeader = (VCFHeaderAdvancedType) headerType; if ((advancedHeader.getType() == Integer.class) || (advancedHeader.getType() == Float.class)) { filterEditor = new IDNumberEditor(); } else if (advancedHeader.getType() == Boolean.class){ filterEditor = new IDFlagEditor(); } else if (advancedHeader.getType() == String.class){ filterEditor = new IDStringEditor(); if (advancedHeader instanceof VCFHeaderElementRecord) { List<Object> elementsList = ((VCFHeaderElementRecord)advancedHeader).getElements(); if ((elementsList != null) && (elementsList.size() > 0)) { List<String> elements = new ArrayList<String>(); for (Object o: elementsList) { elements.add(o.toString()); } ((IDStringEditor)filterEditor).setDefaultElements(elements); } } } if (advancedHeader.getId().equals("GT")) { specialFilterEditor = new IDGTEditor(); } } else if (headerType instanceof VCFHeaderType) { VCFHeaderType header = headerType; if (header.getColumnCategory() == VCFColumnName.ALT) { filterEditor = new IDStringEditor(); } else if (headerType instanceof VCFHeaderFilterType) { filterEditor = new IDFlagEditor(); } } if (filterEditor != null) { filterEditor.setHeaderType(headerType); } if (specialFilterEditor != null) { specialFilterEditor.setHeaderType(headerType); } } /** * First initialization when the component is created. * Restores the values of a filter if this filter is edited * @param element */ private void initialize(FilterInterface element) { if( (filterEditor != null) && (element != null)) { if (element instanceof IDFilterInterface) { IDFilterInterface filter = (IDFilterInterface) element; if (element instanceof GenotypeIDFilter) { specialFilterEditor.initializesPanel(filter); showSpecialPanel(); } else { filterEditor.initializesPanel(filter); showRegularPanel(); } } } checkIfSelectionIsValid(); } /** * @return true if the current values selected by the user are valid, false otherwise */ public boolean isSelectionValid() { return isSelectionValid; } @Override public void propertyChange(PropertyChangeEvent evt) { checkIfSelectionIsValid(); } /** * Sets the VCF field being edited and adapt * the panel to the type of this field. * @param headerType */ public void setHeaderType(VCFHeaderType headerType) { initEditors(headerType); JPanel panel; if (filterEditor != null) { panel = getCustomPanel(); } else { panel = new JPanel(); } removeAll(); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1; gbc.weighty = 1; gbc.anchor = GridBagConstraints.FIRST_LINE_START; add(panel, gbc); revalidate(); repaint(); checkIfSelectionIsValid(); } /** * Shows the panel for regular filters */ private void showRegularPanel () { if (specialFilterEditor != null) { specialFilterEditor.setVisible(false); } if (regularRadioBox != null) { regularRadioBox.setSelected(true); } filterEditor.setVisible(true); } /** * Shows the panel for special filters */ private void showSpecialPanel () { filterEditor.setVisible(false); if (specialRadioBox != null) { specialRadioBox.setSelected(true); } if (specialFilterEditor != null) { specialFilterEditor.setVisible(true); } } }