/******************************************************************************* * 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.controlPanel; 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.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import edu.yu.einstein.genplay.core.manager.project.ProjectManager; import edu.yu.einstein.genplay.core.manager.project.ProjectWindow; import edu.yu.einstein.genplay.core.manager.project.ProjectZoom; import edu.yu.einstein.genplay.dataStructure.chromosome.Chromosome; import edu.yu.einstein.genplay.dataStructure.genomeWindow.SimpleGenomeWindow; import edu.yu.einstein.genplay.gui.action.project.PAMoveFarLeft; import edu.yu.einstein.genplay.gui.action.project.PAMoveFarRight; import edu.yu.einstein.genplay.gui.action.project.PAMoveLeft; import edu.yu.einstein.genplay.gui.action.project.PAMoveRight; import edu.yu.einstein.genplay.gui.event.genomeWindowEvent.GenomeWindowEvent; import edu.yu.einstein.genplay.gui.event.genomeWindowEvent.GenomeWindowListener; import edu.yu.einstein.genplay.util.Images; import edu.yu.einstein.genplay.util.NumberFormats; /** * The ZoomPanel part of the {@link ControlPanel} * @author Julien Lajugie * @version 0.1 */ final class ZoomPanel extends JPanel implements MouseWheelListener, GenomeWindowListener { private static final long serialVersionUID = -8481919273684304592L; // generated ID private static final int ZOOM_SLIDE_WIDTH = 400; // width of the zoom slider private final JLabel jlZoom; // zoom label private final JButton jbPlus; // button '+' private final JButton jbMinus; // button '-' private final JSlider jsZoom; // zoom slider private final ProjectZoom projectZoom; // ZoomManager private final ProjectWindow projectWindow; // Instance of the Genome Window Manager /** * Creates an instance of {@link ZoomPanel} * @param genomeWindow a {@link SimpleGenomeWindow} */ ZoomPanel() { projectZoom = ProjectManager.getInstance().getProjectZoom(); projectWindow = ProjectManager.getInstance().getProjectWindow(); jlZoom = new JLabel(); setZoomLabel(projectWindow.getGenomeWindow().getSize()); jbMinus = new JButton(); jbMinus.setIcon(new ImageIcon(Images.getMinusImage())); jbMinus.setRolloverIcon(new ImageIcon(Images.getMinusRolledOverImage())); jbMinus.setBorderPainted(false); jbMinus.setFocusPainted(false); jbMinus.setMargin(new Insets(0, 0, 0, 0)); jbMinus.setContentAreaFilled(false); jbMinus.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { zoomChanged(projectZoom.getNextZoomOut(projectWindow.getGenomeWindow().getSize())); } }); jbPlus = new JButton(); jbPlus.setIcon(new ImageIcon(Images.getPlusImage())); jbPlus.setRolloverIcon(new ImageIcon(Images.getPlusRolledOverImage())); jbPlus.setBorderPainted(false); jbPlus.setFocusPainted(false); jbPlus.setMargin(new Insets(0, 0, 0, 0)); jbPlus.setContentAreaFilled(false); jbPlus.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { zoomChanged(projectZoom.getNextZoomIn(projectWindow.getGenomeWindow().getSize())); } }); int maximumZoom = projectWindow.getGenomeWindow().getChromosome().getLength() * 2; jsZoom = new JSlider(SwingConstants.HORIZONTAL, 0, projectZoom.getZoomIndex(maximumZoom), projectZoom.getZoomIndex(projectWindow.getGenomeWindow().getSize())); jsZoom.setOpaque(false); jsZoom.setMinorTickSpacing(1); jsZoom.setPaintTicks(true); jsZoom.setInverted(true); jsZoom.setPreferredSize(new Dimension(ZOOM_SLIDE_WIDTH, jsZoom.getPreferredSize().height)); jsZoom.setMinimumSize(new Dimension(ZOOM_SLIDE_WIDTH, jsZoom.getMinimumSize().height)); jsZoom.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (projectZoom.getZoomIndex(projectWindow.getGenomeWindow().getSize()) != jsZoom.getValue()) { zoomChanged(projectZoom.getZoom(jsZoom.getValue())); } } }); // Add the components setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 3; gbc.weightx = 1; gbc.weighty = 0; add(jlZoom, gbc); gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_END; gbc.gridx = 0; gbc.gridy = 1; gbc.weightx = 0; gbc.weighty = 0; add(jbMinus, gbc); gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridx = 1; gbc.gridy = 1; gbc.weightx = 1; gbc.weighty = 0; add(jsZoom, gbc); gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.gridx = 2; gbc.gridy = 1; gbc.weightx = 0; gbc.weighty = 0; add(jbPlus, gbc); addMouseWheelListener(this); // Deactivate slider key listener (bother the main frame key event management) jsZoom.getInputMap().put(PAMoveLeft.ACCELERATOR, "none"); jsZoom.getInputMap().put(PAMoveFarLeft.ACCELERATOR, "none"); jsZoom.getInputMap().put(PAMoveRight.ACCELERATOR, "none"); jsZoom.getInputMap().put(PAMoveFarRight.ACCELERATOR, "none"); setOpaque(false); } @Override public void genomeWindowChanged(GenomeWindowEvent evt) { // we notify the gui int currentZoom = evt.getNewWindow().getSize(); setZoomLabel(currentZoom); // if the chromosome changes we change the maximum zoom if (evt.getNewWindow().getChromosome() != evt.getOldWindow().getChromosome()) { int oldMaximumZoom = evt.getOldWindow().getChromosome().getLength() * 2; int newMaximumZoom = evt.getNewWindow().getChromosome().getLength() * 2; // if the new zoom value is greatter than the old max zoom we change the max first if (currentZoom > oldMaximumZoom) { jsZoom.setMaximum(projectZoom.getZoomIndex(newMaximumZoom)); jsZoom.setValue(projectZoom.getZoomIndex(currentZoom)); } else { // else we change the value first because the new max could be smaller than the old value jsZoom.setValue(projectZoom.getZoomIndex(currentZoom)); jsZoom.setMaximum(projectZoom.getZoomIndex(newMaximumZoom)); } } else { jsZoom.setValue(projectZoom.getZoomIndex(currentZoom)); } } @Override public void mouseWheelMoved(MouseWheelEvent mwe) { int currentZoom = projectWindow.getGenomeWindow().getSize(); for (int i = 0; i < Math.abs(mwe.getWheelRotation()); i++) { if (mwe.getWheelRotation() > 0) { zoomChanged(projectZoom.getNextZoomIn(currentZoom)); } else { zoomChanged(projectZoom.getNextZoomOut(currentZoom)); } } } /** * Sets the text of the zoom label */ private void setZoomLabel(int zoom) { String text = "Size: " + NumberFormats.getPositionFormat().format(zoom) + "bp"; jlZoom.setText(text); } /** * Called when the zoom changes * @param newZoom new zoom value */ void zoomChanged(int newZoom) { int currentZoom = projectWindow.getGenomeWindow().getSize(); int maximumZoom = projectWindow.getGenomeWindow().getChromosome().getLength() * 2; if (newZoom > maximumZoom) { newZoom = maximumZoom; } if (newZoom != currentZoom) { double halfZoom = newZoom / (double)2; Chromosome chromosome = projectWindow.getGenomeWindow().getChromosome(); int start = (int)(projectWindow.getGenomeWindow().getMiddlePosition() - halfZoom); int stop = start + newZoom; SimpleGenomeWindow newGenomeWindow = new SimpleGenomeWindow(chromosome, start, stop); projectWindow.setGenomeWindow(newGenomeWindow); } } }