From d82eea381b4172c4a9d851dee74508429e9394e4 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 26 Jul 2018 11:15:44 +0100 Subject: [PATCH] JAL-3071 SeqPanel scroll thread now interruptible in JalviewJS --- src/jalview/gui/SeqPanel.java | 182 ++++++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 50 deletions(-) diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index 5050150..330a962 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -22,6 +22,7 @@ package jalview.gui; 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; @@ -55,6 +56,8 @@ import java.awt.Color; 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; @@ -67,6 +70,7 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JToolTip; import javax.swing.SwingUtilities; +import javax.swing.Timer; import javax.swing.ToolTipManager; /** @@ -1623,9 +1627,9 @@ public class SeqPanel extends JPanel @Override public void mouseExited(MouseEvent e) { - if (!av.getWrapAlignment() && mouseDragging && scrollThread == null) + if (mouseDragging) { - scrollThread = new ScrollThread(); + startScrolling(e.getPoint()); } } @@ -2036,29 +2040,87 @@ public class SeqPanel extends JPanel /** * 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 @@ -2066,12 +2128,14 @@ public class SeqPanel extends JPanel 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 */ @@ -2085,7 +2149,7 @@ public class SeqPanel extends JPanel */ public void stopScrolling() { - threadRunning = false; + keepRunning = false; } /** @@ -2096,48 +2160,12 @@ public class SeqPanel extends JPanel @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); @@ -2145,6 +2173,60 @@ public class SeqPanel extends JPanel { } } + SeqPanel.this.scrollThread = null; + } + + /** + * Scrolls + * + * 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; } } -- 1.7.10.2