/******************************************************************************* * 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.track; import edu.yu.einstein.genplay.core.manager.project.ProjectChromosomes; import edu.yu.einstein.genplay.core.manager.project.ProjectManager; import edu.yu.einstein.genplay.core.manager.project.ProjectWindow; import edu.yu.einstein.genplay.dataStructure.chromosome.Chromosome; import edu.yu.einstein.genplay.dataStructure.genomeWindow.SimpleGenomeWindow; import edu.yu.einstein.genplay.exception.ExceptionManager; /** * Singleton used by tracks to scroll the genome window displayed when the scrolling mode is on * (the scrolling mode can be turned on and off using the mouse middle button) * @author Julien Lajugie */ public class ScrollingManager { /** * The ScrollModeThread class is used to scroll the track horizontally * when the scroll mode is on (ie when the middle button of the mouse is clicked) * @author Julien Lajugie */ private class ScrollingThread extends Thread { @Override public void run() { synchronized (this) { Thread thisThread = Thread.currentThread(); ProjectWindow projectWindow = ProjectManager.getInstance().getProjectWindow(); while (scrollingThread == thisThread) { Chromosome chromo = projectWindow.getGenomeWindow().getChromosome(); int start = projectWindow.getGenomeWindow().getStart() + scrollingIntensity; int stop = projectWindow.getGenomeWindow().getStop() + scrollingIntensity; SimpleGenomeWindow newWindow = new SimpleGenomeWindow(chromo, start, stop); if (newWindow.getMiddlePosition() < ProjectChromosomes.FIRST_BASE_POSITION) { start = ProjectChromosomes.FIRST_BASE_POSITION - (projectWindow.getGenomeWindow().getSize() / 2); stop = start + projectWindow.getGenomeWindow().getSize(); newWindow = new SimpleGenomeWindow(chromo, start, stop); } else if (newWindow.getMiddlePosition() > newWindow.getChromosome().getLength()) { stop = newWindow.getChromosome().getLength() + (projectWindow.getGenomeWindow().getSize() / 2); start = stop - projectWindow.getGenomeWindow().getSize(); newWindow = new SimpleGenomeWindow(chromo, start, stop); } projectWindow.setGenomeWindow(newWindow); yield(); try { if ((scrollingIntensity == 1) || (scrollingIntensity == -1)) { sleep(100); } else { sleep(10); } } catch (InterruptedException e) { ExceptionManager.getInstance().caughtException(e); } } } } } private static ScrollingManager instance = null; /** * @return the instance of the {@link ScrollingManager} singleton */ public synchronized static ScrollingManager getInstance() { if (instance == null) { // we synchronize to make sure that there is no 2 instances created synchronized(ScrollingManager.class) { if (instance == null) { instance = new ScrollingManager(); } } } return instance; } private ScrollingThread scrollingThread; // thread executed when the scroll mode is on private int scrollingIntensity; // intensity of the scroll. /** * Creates an instance of {@link ScrollingManager} */ private ScrollingManager() { scrollingIntensity = 0; } /** * @return the value of the scrolling intensity */ public int getScrollingIntensity() { return scrollingIntensity; } /** * @return true if the scrolling mode is on, false if it's off */ public boolean isScrollingEnabled() { return scrollingThread != null; } /** * @return true if the scrolling is enable and going left */ public boolean isScrollingLeft() { return isScrollingEnabled() && (getScrollingIntensity() < 0); } /** * @return true if the scrolling is enable and going right */ public boolean isScrollingRight() { return isScrollingEnabled() && (getScrollingIntensity() > 0); } /** * Turns on or off the track scrolling mode * @param enabled true if the scrolling mode should be enabled, false otherwise */ public void setScrollingEnabled(boolean enabled) { if (enabled) { scrollingThread = new ScrollingThread(); scrollingThread.start(); } else { scrollingThread = null; } } /** * Set the intensity of the scrolling. * Positive and negative intensities scroll the windows in opposite directions * @param distance horizontal distance between the cursor and the middle of the track. * The distance should be negative if the cursor is located left of the middle of the track */ public void setScrollingIntensity(int distance) { ProjectWindow projectWindow = ProjectManager.getInstance().getProjectWindow(); double scrollingIntensityTmp = projectWindow.screenToGenomeWidth(Math.abs(distance)); if (distance < 0) { scrollingIntensity = (int) (-(scrollingIntensityTmp / 10d) - 1); } else { scrollingIntensity = (int) (scrollingIntensityTmp / 10d) + 1; } } }