import jalview.api.AlignViewportI;
import jalview.bin.Cache;
+import jalview.bin.Jalview;
import jalview.commands.EditCommand;
import jalview.commands.EditCommand.Action;
import jalview.commands.EditCommand.Edit;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.SwingUtilities;
+import javax.swing.Timer;
import javax.swing.ToolTipManager;
/**
@Override
public void mouseExited(MouseEvent e)
{
- if (!av.getWrapAlignment() && mouseDragging && scrollThread == null)
+ if (mouseDragging)
{
- scrollThread = new ScrollThread();
+ startScrolling(e.getPoint());
}
}
/**
* Starts a thread to scroll the alignment, towards a given mouse position
- * outside the panel bounds
+ * outside the panel bounds, unless the alignment is in wrapped mode
*
* @param mousePos
*/
void startScrolling(Point mousePos)
{
- if (scrollThread == null)
+ /*
+ * set this.mouseDragging in case this was called from
+ * a drag in ScalePanel or AnnotationPanel
+ */
+ mouseDragging = true;
+ if (!av.getWrapAlignment() && mouseDragging && scrollThread == null)
{
scrollThread = new ScrollThread();
+ scrollThread.setMousePosition(mousePos);
+ if (!Jalview.isJS())
+ {
+ /*
+ * Java - run in a new thread
+ */
+ scrollThread.start();
+ }
+ else
+ {
+ /*
+ * Javascript - run every 20ms until scrolling stopped
+ * or reaches the limit of scrollable alignment
+ */
+ // java.util.Timer version:
+ // Timer t = new Timer("ScrollThreadTimer", true);
+ // TimerTask task = new TimerTask()
+ // {
+ // @Override
+ // public void run()
+ // {
+ // if (!scrollThread.scrollOnce())
+ // {
+ // cancel();
+ // }
+ // }
+ // };
+ // t.schedule(task, 20, 20);
+ Timer t = new Timer(20, new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if (scrollThread != null)
+ {
+ // if (!scrollOnce() {t.stop();}) gives compiler error :-(
+ scrollThread.scrollOnce();
+ }
+ }
+ });
+ t.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if (scrollThread == null)
+ {
+ // finished and nulled itself
+ t.stop();
+ }
+ }
+ });
+ t.start();
+ }
}
-
- mouseDragging = true;
- scrollThread.setMousePosition(mousePos);
}
/**
- * Performs scrolling of the visible alignment left, right, up or down
+ * Performs scrolling of the visible alignment left, right, up or down, until
+ * scrolling is stopped by calling stopScrolling, mouse drag is ended, or the
+ * limit of the alignment is reached
*/
class ScrollThread extends Thread
{
private Point mousePos;
- private volatile boolean threadRunning = true;
+ private volatile boolean keepRunning = true;
/**
* Constructor
public ScrollThread()
{
setName("SeqPanel$ScrollThread");
- start();
}
/**
* Sets the position of the mouse that determines the direction of the
- * scroll to perform
+ * scroll to perform. If this is called as the mouse moves, scrolling should
+ * respond accordingly. For example, if the mouse is dragged right, scroll
+ * right should start; if the drag continues down, scroll down should also
+ * happen.
*
* @param p
*/
*/
public void stopScrolling()
{
- threadRunning = false;
+ keepRunning = false;
}
/**
@Override
public void run()
{
- while (threadRunning && mouseDragging)
+ while (keepRunning)
{
if (mousePos != null)
{
- boolean scrolled = false;
- ViewportRanges ranges = SeqPanel.this.av.getRanges();
-
- /*
- * scroll up or down
- */
- if (mousePos.y < 0)
- {
- // mouse is above this panel - try scroll up
- scrolled = ranges.scrollUp(true);
- }
- else if (mousePos.y >= getHeight())
- {
- // mouse is below this panel - try scroll down
- scrolled = ranges.scrollUp(false);
- }
-
- /*
- * scroll left or right
- */
- if (mousePos.x < 0)
- {
- scrolled |= ranges.scrollRight(false);
- }
- else if (mousePos.x >= getWidth())
- {
- scrolled |= ranges.scrollRight(true);
- }
- if (!scrolled)
- {
- /*
- * we have reached the limit of the visible alignment - quit
- */
- threadRunning = false;
- SeqPanel.this.ap.repaint();
- }
+ keepRunning = scrollOnce();
}
-
try
{
Thread.sleep(20);
{
}
}
+ SeqPanel.this.scrollThread = null;
+ }
+
+ /**
+ * Scrolls
+ * <ul>
+ * <li>one row up, if the mouse is above the panel</li>
+ * <li>one row down, if the mouse is below the panel</li>
+ * <li>one column left, if the mouse is left of the panel</li>
+ * <li>one column right, if the mouse is right of the panel</li>
+ * </ul>
+ * Answers true if a scroll was performed, false if not - meaning either
+ * that the mouse position is within the panel, or the edge of the alignment
+ * has been reached.
+ */
+ boolean scrollOnce()
+ {
+ /*
+ * quit after mouseUp ensures interrupt in JalviewJS
+ */
+ if (!mouseDragging)
+ {
+ return false;
+ }
+
+ boolean scrolled = false;
+ ViewportRanges ranges = SeqPanel.this.av.getRanges();
+
+ /*
+ * scroll up or down
+ */
+ if (mousePos.y < 0)
+ {
+ // mouse is above this panel - try scroll up
+ scrolled = ranges.scrollUp(true);
+ }
+ else if (mousePos.y >= getHeight())
+ {
+ // mouse is below this panel - try scroll down
+ scrolled = ranges.scrollUp(false);
+ }
+
+ /*
+ * scroll left or right
+ */
+ if (mousePos.x < 0)
+ {
+ scrolled |= ranges.scrollRight(false);
+ }
+ else if (mousePos.x >= getWidth())
+ {
+ scrolled |= ranges.scrollRight(true);
+ }
+ return scrolled;
}
}