/******************************************************************************* * 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.addOrEditVariantLayer; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.security.InvalidParameterException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import edu.yu.einstein.genplay.dataStructure.enums.VariantType; import edu.yu.einstein.genplay.gui.MGDisplaySettings.VariantLayerDisplaySettings; import edu.yu.einstein.genplay.util.colors.Colors; import edu.yu.einstein.genplay.util.colors.GenPlayColorChooser; /** * Panel to select the variant to display * @author Julien Lajugie */ class VariantTypeSelectionPanel extends JPanel { /** * Data displayed in the VariantTypeSelectionPanel * @author Julien Lajugie */ private class VariantTypeSelectionModel { /** Colors currently selected */ private final Map<VariantLayerDisplaySettings, Color[]> colorSelection; /** Selection state of the variant types */ private final Map<VariantLayerDisplaySettings, boolean[]> typeSelection; /** * Creates a new instance of {@link VariantTypeSelectionModel} * @param genomes genomes to edit */ VariantTypeSelectionModel(List<VariantLayerDisplaySettings> genomes) { colorSelection = new HashMap<VariantLayerDisplaySettings, Color[]>(genomes.size()); typeSelection = new HashMap<VariantLayerDisplaySettings, boolean[]>(genomes.size()); for(VariantLayerDisplaySettings currentGenome: genomes) { colorSelection.put(currentGenome, Arrays.copyOf(DEFAULT_VARIANT_COLOR, DEFAULT_VARIANT_COLOR.length)); typeSelection.put(currentGenome, new boolean[3]); for (VariantType selectedType: currentGenome.getVariationTypeList()) { int index = currentGenome.getVariationTypeList().indexOf(selectedType); setSelected(currentGenome, selectedType, true); setColor(currentGenome, selectedType, currentGenome.getColorList().get(index)); } } } /** * @param genome a genome * @param variantType a type of variant (insertion, deletion, SNP) * @return the color currently selected for the specified variant type of the specified genome */ Color getColor(VariantLayerDisplaySettings genome, VariantType variantType) { int index = getVariantTypeIndex(variantType); Color[] colors = colorSelection.get(genome); return colors[index]; } /** * @param genome a genome * @param variantType a type of variant (insertion, deletion, SNP) * @return true if the specified variant type of the specified genome is selected, false otherwise */ boolean isSelected(VariantLayerDisplaySettings genome, VariantType variantType) { int index = getVariantTypeIndex(variantType); boolean[] selectedTypes = typeSelection.get(genome); return selectedTypes[index]; } /** * Sets the colors of the specified variant type of the specified genome * @param genome a genome * @param variantType a type of variant (insertion, deletion, SNP) * @param color a color to set */ void setColor(VariantLayerDisplaySettings genome, VariantType variantType, Color color) { int index = getVariantTypeIndex(variantType); Color[] colors = colorSelection.get(genome); colors[index] = color; if (genome.getVariationTypeList().contains(variantType)) { int indexToSet = genome.getVariationTypeList().indexOf(variantType); genome.getColorList().set(indexToSet, color); } } /** * Sets the selection state of the specified variant type of the specified genome * @param genome a genome * @param variantType a type of variant (insertion, deletion, SNP) * @param isSelected true if it's selected, false otherwise */ void setSelected(VariantLayerDisplaySettings genome, VariantType variantType, boolean isSelected) { int index = getVariantTypeIndex(variantType); boolean[] selectedTypes = typeSelection.get(genome); selectedTypes[index] = isSelected; if (isSelected) { if (!genome.getVariationTypeList().contains(variantType)) { genome.getVariationTypeList().add(variantType); genome.getColorList().add(getColor(genome, variantType)); } } else { if (genome.getVariationTypeList().contains(variantType)) { int indexToRemove = genome.getVariationTypeList().indexOf(variantType); genome.getVariationTypeList().remove(indexToRemove); genome.getColorList().remove(indexToRemove); } } } } /** Array of default variation colors (Insertion, Deletion, SNPs) */ private static final Color[] DEFAULT_VARIANT_COLOR = {Colors.LIGHT_BLUE, Colors.GREEN, Colors.RED}; /** Generated serial version ID */ private static final long serialVersionUID = -4060807866730514644L; /** Property name of the selected variant types*/ static final String SELECTED_VARIANT_TYPES_PROPERTY_NAME = "selectedVariantTypes"; /** Index of the SNP color in the color list */ private static final int SNP_INDEX = 0; /** Index of the insertion color in the color list */ private static final int INSERTION_INDEX = 1; /** Index of the deletion color in the color list */ private static final int DELETION_INDEX = 2; /** Selected genome with it's current color and variant type selection */ private VariantLayerDisplaySettings selectedGenome; /** Data displayed in this panel */ private final VariantTypeSelectionModel model; /** * Creates an instance of {@link VariantTypeSelectionPanel} * @param genomes {@link VariantLayerDisplaySettings} to edit */ VariantTypeSelectionPanel(List<VariantLayerDisplaySettings> genomes) { if ((genomes == null) || genomes.isEmpty()) { throw new InvalidParameterException("The list of genome to edit cannot be null or empty"); } model = new VariantTypeSelectionModel(genomes); setSelectedGenome(genomes.get(0)); } /** * Create a check box to select / unselect a variant type * @param variantType * @return a new {@link JCheckBox} */ private JCheckBox createCheckBox(final VariantType variantType) { final JCheckBox checkBox = new JCheckBox(); checkBox.setToolTipText("Enable/Disable " + variantType.toString().toLowerCase() + "."); checkBox.setSelected(model.isSelected(selectedGenome, variantType)); checkBox.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { model.setSelected(selectedGenome, variantType, checkBox.isSelected()); firePropertyChange(SELECTED_VARIANT_TYPES_PROPERTY_NAME, null, selectedGenome); } }); return checkBox; } /** * Creates an button to select a color for a variant type * @param variantType * @return a clickable {@link JPanel} to select a color */ private JPanel createColorButton(final VariantType variantType) { JPanel colorButton = new JPanel(); colorButton.setOpaque(true); colorButton.setPreferredSize(new Dimension(13, 13)); colorButton.setToolTipText("Select color for " + variantType.toString().toLowerCase() + "."); colorButton.setBackground(model.getColor(selectedGenome, variantType)); colorButton.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { JPanel button = (JPanel) e.getSource(); Color newColor = GenPlayColorChooser.showDialog(VariantTypeSelectionPanel.this, button.getBackground()); if (newColor != null) { button.setBackground(newColor); model.setColor(selectedGenome, variantType, newColor); } } }); return colorButton; } /** * Creates the panel to select variant types and there colors */ private void createVariationSelectionPanel () { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.insets = new Insets(5, 5, 5, 5); gbc.gridy = 0; gbc.weightx = 1; gbc.weighty = 1; VariantType[] types = {VariantType.SNPS, VariantType.INSERTION, VariantType.DELETION}; for(VariantType vt: types) { JLabel variantTypeLabel = new JLabel(vt.toString()); JCheckBox checkBox = createCheckBox(vt); JPanel colorButton = createColorButton(vt); // Variation name gbc.gridx = 0; add(variantTypeLabel, gbc); // Selection button gbc.gridx = 1; add(checkBox, gbc); // Color button gbc.gridx = 2; add(colorButton, gbc); gbc.gridy++; } setBorder(BorderFactory.createTitledBorder("Variant Type(s)")); } /** * @param variantType * @return the index of the spcified variant type */ private final int getVariantTypeIndex(VariantType variantType) { switch (variantType) { case SNPS: return SNP_INDEX; case INSERTION: return INSERTION_INDEX; case DELETION: return DELETION_INDEX; default: throw new InvalidParameterException("Invalid variant type: " + variantType.toString()); } } /** * Sets the selected genome and refresh the content of the panel * @param selectedGenome */ public void setSelectedGenome(VariantLayerDisplaySettings selectedGenome) { this.selectedGenome = selectedGenome; removeAll(); createVariationSelectionPanel(); revalidate(); } }