/******************************************************************************* * 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; import java.awt.Component; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Arrays; import java.util.List; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.border.TitledBorder; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import edu.yu.einstein.genplay.core.manager.project.ProjectManager; import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFFile.VCFFile; 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.VCFFilter; import edu.yu.einstein.genplay.core.multiGenome.filter.VCFID.IDFilterInterface; import edu.yu.einstein.genplay.core.multiGenome.filter.utils.FormatFilterOperatorType; import edu.yu.einstein.genplay.dataStructure.enums.VCFColumnName; import edu.yu.einstein.genplay.gui.MGDisplaySettings.FiltersData; import edu.yu.einstein.genplay.gui.dialog.layerChooser.LayerChooserPanel; import edu.yu.einstein.genplay.gui.dialog.layerChooser.LayerChooserTableModel; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.panels.FilePanel; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.panels.FilterIDPanel; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.panels.FilterValuesPanel; import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterDialog.panels.MultiGenomePanel; import edu.yu.einstein.genplay.gui.mainFrame.MainFrame; import edu.yu.einstein.genplay.gui.track.layer.Layer; import edu.yu.einstein.genplay.gui.track.layer.LayerType; import edu.yu.einstein.genplay.util.Images; import edu.yu.einstein.genplay.util.Utils; /** * Dialog to create or edit filters * @author Julien Lajugie */ public class AddOrEditVariantFiltersDialog extends JDialog implements PropertyChangeListener { /** Generated serial ID */ private static final long serialVersionUID = -8357422979931946414L; /** 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; /** Preferred height of the layer chooser */ private static final int LAYER_PANEL_PREFERRED_HEIGHT = 200; /** Preferred width of the panels that take up the entire dialog width */ public static final int LARGE_PANELS_PREFERRED_WIDTH = 700; /** * Show a {@link AddOrEditVariantFiltersDialog} to create a filter * @param parentComponent parent component of the dialog * @return a new filter */ public static FiltersData showAddDialog(Component parentComponent) { AddOrEditVariantFiltersDialog dialog = new AddOrEditVariantFiltersDialog(null); dialog.setTitle("Create Filter"); dialog.setLocationRelativeTo(parentComponent); dialog.setVisible(true); if (dialog.approved == APPROVE_OPTION) { return dialog.filtersData; } else { return null; } } /** * Show a {@link AddOrEditVariantFiltersDialog} to edit a filter * @param parentComponent parent component of the dialog * @return a filter edited */ public static FiltersData showEditDialog(Component parentComponent, FiltersData data) { AddOrEditVariantFiltersDialog dialog = new AddOrEditVariantFiltersDialog(data); dialog.setTitle("Edit Filter"); dialog.setLocationRelativeTo(parentComponent); dialog.setVisible(true); if (dialog.approved == APPROVE_OPTION) { return dialog.filtersData; } else { return null; } } private final FilePanel filePanel; // panel to select a file private final LayerChooserPanel layerPanel; // panel to select a layer private final FilterIDPanel idPanel; // panel to select the VCF field to filter private final FilterValuesPanel valuePanel; // panel to select the values of the filter private final MultiGenomePanel genomePanel; // panel to select a genome private final JButton jbOk; // ok button private FiltersData filtersData; // The current filter data (can be null) private int approved = CANCEL_OPTION; // equals APPROVE_OPTION if user clicked OK, CANCEL_OPTION if not /** * Creates an instance of {@link AddOrEditVariantFiltersDialog} * @param filtersData {@link FiltersData} to edit. Should be null if the dialog is used to create a new filter */ private AddOrEditVariantFiltersDialog(FiltersData filtersData) { super(); List<VCFFile> fileList = ProjectManager.getInstance().getMultiGenomeProject().getAllVCFFiles(); VCFFile selectedFile; List<VCFHeaderType> headerList; VCFHeaderType selectedHeader; List<String> selectedGenomes = null; FormatFilterOperatorType selectedOperator = null; FilterInterface filterInterface = null; if(filtersData == null) { selectedFile = fileList.get(0); headerList = selectedFile.getHeader().getAllSortedHeader(); selectedHeader = headerList.get(0); } else { this.filtersData = filtersData; selectedFile = filtersData.getReader(); headerList = selectedFile.getHeader().getAllSortedHeader(); selectedHeader = ((IDFilterInterface) filtersData.getFilter()).getHeaderType(); filterInterface = this.filtersData.getFilter(); selectedGenomes = ((IDFilterInterface) filtersData.getMGFilter().getFilter()).getGenomeNames(); selectedOperator = ((IDFilterInterface) filtersData.getMGFilter().getFilter()).getOperator(); } filePanel = new FilePanel(fileList, selectedFile); layerPanel = createLayerChooserPanel(); idPanel = new FilterIDPanel(headerList, selectedHeader); valuePanel = new FilterValuesPanel(selectedHeader, filterInterface); genomePanel = new MultiGenomePanel(selectedFile.getHeader().getGenomeNames(), selectedHeader, selectedGenomes, selectedOperator); jbOk = new JButton("Ok"); JPanel validationPanel = createValidationPanel(); registerListeners(); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1; gbc.gridwidth = 2; add(filePanel, gbc); gbc.gridy = 1; add(layerPanel, gbc); gbc.gridy = 2; add(idPanel, gbc); gbc.gridwidth = 1; gbc.gridy = 3; add(valuePanel, gbc); gbc.gridx = 1; gbc.weightx = 0.9; add(genomePanel, gbc); gbc.gridwidth = 2; gbc.weightx = 1; gbc.gridy = 4; gbc.gridx = 0; add(validationPanel, gbc); getContentPane().setBackground(validationPanel.getBackground()); setIconImages(Images.getApplicationImages()); setModalityType(ModalityType.APPLICATION_MODAL); setResizable(false); pack(); } /** * @return create the panel to choose layers */ private LayerChooserPanel createLayerChooserPanel() { List<Layer<?>> availableLayers = MainFrame.getInstance().getTrackListPanel().getModel().getAllLayers(); availableLayers = Utils.getLayers(availableLayers, new LayerType[] {LayerType.VARIANT_LAYER}); List<Layer<?>> selectedLayers = null; if ((filtersData != null) && (filtersData.getLayers() != null)) { selectedLayers = Arrays.asList(filtersData.getLayers()); } LayerChooserPanel chooser = new LayerChooserPanel(availableLayers, selectedLayers, new LayerType[] {LayerType.VARIANT_LAYER}, true); chooser.setBorder(new TitledBorder("Select layer(s) to filter")); TableColumnModel tcm = chooser.getTable().getColumnModel(); TableColumn layerTypeColumn = tcm.getColumn(LayerChooserTableModel.LAYER_TYPE_INDEX); tcm.removeColumn(layerTypeColumn); chooser.setPreferredSize(new Dimension(LARGE_PANELS_PREFERRED_WIDTH, LAYER_PANEL_PREFERRED_HEIGHT)); chooser.setMinimumSize(chooser.getPreferredSize()); return chooser; } /** * Creates the panel that contains OK and CANCEL buttons * @return the panel */ private JPanel createValidationPanel() { // Creates the ok button jbOk.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { approved = APPROVE_OPTION; updateFilter(); setVisible(false); } }); // Creates the cancel button JButton jbCancel = new JButton("Cancel"); jbCancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setVisible(false); } }); jbOk.setPreferredSize(jbCancel.getPreferredSize()); jbOk.setEnabled(isSelectionValid()); // Creates the panel JPanel panel = new JPanel(); panel.add(jbOk); panel.add(jbCancel); getRootPane().setDefaultButton(jbOk); // Returns the panel return panel; } /** * @return true if the current selection of filter is valid (all field filled, at least one layer selected ...) */ private boolean isSelectionValid() { if ((layerPanel.getSelectedLayers() == null) || layerPanel.getSelectedLayers().isEmpty()) { return false; } if ((genomePanel != null) && genomePanel.isVisible() && !genomePanel.isSelectionValid()) { return false; } if (!valuePanel.isSelectionValid()) { return false; } return true; } @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(FilePanel.FILE_CHANGE_PROPERTY_NAME)) { VCFFile vcfFile = (VCFFile) evt.getNewValue(); genomePanel.setGenomeList(vcfFile.getHeader().getGenomeNames()); idPanel.setFilters(vcfFile.getHeader().getAllSortedHeader()); } else if (evt.getPropertyName().equals(FilterIDPanel.FILTER_ID_PROPERTY_NAME)) { valuePanel.setHeaderType((VCFHeaderType) evt.getNewValue()); genomePanel.setHeaderType((VCFHeaderType) evt.getNewValue()); } jbOk.setEnabled(isSelectionValid()); } /** * Register this listener to the different panel to receive event notifications */ private void registerListeners() { filePanel.addPropertyChangeListener(FilePanel.FILE_CHANGE_PROPERTY_NAME, this); layerPanel.addPropertyChangeListener(LayerChooserPanel.SELECTED_LAYERS_PROPERTY_NAME, this); idPanel.addPropertyChangeListener(FilterIDPanel.FILTER_ID_PROPERTY_NAME, this); valuePanel.addPropertyChangeListener(FilterValuesPanel.IS_SELECTION_VALID_PROPERTY_NAME, this); genomePanel.addPropertyChangeListener(MultiGenomePanel.IS_SELECTION_VALID_PROPERTY_NAME, this); } /** * Retrieves all the information from the panel in order to create/set the filter data object. * If a current filter data has been defined, it will be set and returned. * If no current filter data has been defined, a new one will be created. */ private void updateFilter() { VCFFile vcfFile = filePanel.getSelectedFile(); IDFilterInterface IDFilter = (IDFilterInterface) valuePanel.getFilter(); Layer<?>[] layers = layerPanel.getSelectedLayers().toArray(new Layer<?>[0]); if ((IDFilter.getHeaderType() != null) && (IDFilter.getHeaderType().getColumnCategory() == VCFColumnName.FORMAT)) { List<String> genomeNames = genomePanel.getSelectedGenomes(); FormatFilterOperatorType operator = genomePanel.getSelectedOperator(); IDFilter.setGenomeNames(genomeNames); IDFilter.setOperator(operator); } else { IDFilter.setGenomeNames(null); IDFilter.setOperator(null); } if (filtersData != null) { ((VCFFilter) filtersData.getMGFilter()).setVCFFile(vcfFile); filtersData.getMGFilter().setFilter(IDFilter); filtersData.setLayers(layers); } else { filtersData = new FiltersData(new VCFFilter(IDFilter, vcfFile), layers); } } }