X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fgui%2FSeqPanel.java;h=845004bdb05d1391565f86889238045bd45eb59a;hb=5640ec0623c6d1205e62f9fe15292f32bfdab7d9;hp=c648e532aba0b4388b7ac610d5509ec169b1d9d2;hpb=eca14f3239efc539413d3c4bc334de80710dd86c;p=jalview.git diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index c648e53..845004b 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -20,8 +20,31 @@ */ package jalview.gui; +import java.awt.BorderLayout; +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; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JToolTip; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.ToolTipManager; + import jalview.api.AlignViewportI; -import jalview.bin.Cache; +import jalview.bin.Console; import jalview.commands.EditCommand; import jalview.commands.EditCommand.Action; import jalview.commands.EditCommand.Edit; @@ -53,24 +76,6 @@ import jalview.viewmodel.AlignmentViewport; import jalview.viewmodel.ViewportRanges; import jalview.viewmodel.seqfeatures.FeatureRendererModel; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Point; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.ToolTipManager; - /** * DOCUMENT ME! * @@ -132,7 +137,7 @@ public class SeqPanel extends JPanel MousePos o = (MousePos) obj; boolean b = (column == o.column && seqIndex == o.seqIndex && annotationIndex == o.annotationIndex); - // System.out.println(obj + (b ? "= " : "!= ") + this); + // jalview.bin.Console.outPrintln(obj + (b ? "= " : "!= ") + this); return b; } @@ -207,13 +212,21 @@ public class SeqPanel extends JPanel StringBuffer keyboardNo2; - java.net.URL linkImageURL; - private final SequenceAnnotationReport seqARep; - StringBuilder tooltipText = new StringBuilder(); + /* + * the last tooltip on mousing over the alignment (or annotation in wrapped mode) + * - the tooltip is not set again if unchanged + * - this is the tooltip text _before_ formatting as html + */ + private String lastTooltip; - String tmpString; + /* + * the last tooltip on mousing over the alignment (or annotation in wrapped mode) + * - used to decide where to place the tooltip in getTooltipLocation() + * - this is the tooltip text _after_ formatting as html + */ + private String lastFormattedTooltip; EditCommand editCommand; @@ -229,11 +242,11 @@ public class SeqPanel extends JPanel */ public SeqPanel(AlignViewport viewport, AlignmentPanel alignPanel) { - linkImageURL = getClass().getResource("/images/link.gif"); - seqARep = new SequenceAnnotationReport(linkImageURL.toString()); + seqARep = new SequenceAnnotationReport(true); ToolTipManager.sharedInstance().registerComponent(this); ToolTipManager.sharedInstance().setInitialDelay(0); ToolTipManager.sharedInstance().setDismissDelay(10000); + this.av = viewport; setBackground(Color.white); @@ -261,6 +274,9 @@ public class SeqPanel extends JPanel /** * Computes the column and sequence row (and possibly annotation row when in * wrapped mode) for the given mouse position + *
+ * Mouse position is not set if in wrapped mode with the cursor either between + * sequences, or over the left or right vertical scale. * * @param evt * @return @@ -325,15 +341,39 @@ public class SeqPanel extends JPanel return new MousePos(col, seqIndex, annIndex); } + + /** + * @param evt + * @return absolute column in alignment nearest to the mouse pointer + */ + int findAlignmentColumn(MouseEvent evt) + { + return findNearestColumn(evt, true); + } + /** * Returns the aligned sequence position (base 0) at the mouse position, or * the closest visible one + *
+ * Returns -1 if in wrapped mode with the mouse over either left or right
+ * vertical scale.
*
* @param evt
* @return
*/
int findColumn(MouseEvent evt)
{
+ return findNearestColumn(evt, false);
+ }
+
+ /**
+ * @param nearestColumn
+ * when false returns negative values for out of bound positions - -1
+ * for scale left/right, <-1 if far to right
+ * @return nearest absolute column to mouse pointer
+ */
+ private int findNearestColumn(MouseEvent evt, boolean nearestColumn)
+ {
int res = 0;
int x = evt.getX();
@@ -357,7 +397,14 @@ public class SeqPanel extends JPanel
if (x < 0)
{
// mouse is over left scale
- return -1;
+ if (!nearestColumn)
+ {
+ return -1;
+ }
+ else
+ {
+ x = 0;
+ }
}
int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
@@ -367,8 +414,15 @@ public class SeqPanel extends JPanel
}
if (x >= cwidth * charWidth)
{
- // mouse is over right scale
- return -1;
+ if (!nearestColumn)
+ {
+ // mouse is over right scale
+ return -1;
+ }
+ else
+ {
+ x = cwidth * charWidth - 1;
+ }
}
wrappedBlock = y / cHeight;
@@ -385,8 +439,14 @@ public class SeqPanel extends JPanel
* rather than right-hand gutter
*/
x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth());
+ if (nearestColumn)
+ {
+ x = Math.max(x, 0);
+ }
+
res = (x / charWidth) + startRes;
res = Math.min(res, av.getRanges().getEndRes());
+
}
if (av.hasHiddenColumns())
@@ -463,45 +523,85 @@ public class SeqPanel extends JPanel
void moveCursor(int dx, int dy)
{
- seqCanvas.cursorX += dx;
- seqCanvas.cursorY += dy;
+ moveCursor(dx, dy, false);
+ }
+ void moveCursor(int dx, int dy, boolean nextWord)
+ {
HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- if (av.hasHiddenColumns() && !hidden.isVisible(seqCanvas.cursorX))
+ if (nextWord)
{
- int original = seqCanvas.cursorX - dx;
int maxWidth = av.getAlignment().getWidth();
-
- if (!hidden.isVisible(seqCanvas.cursorX))
- {
- int visx = hidden.absoluteToVisibleColumn(seqCanvas.cursorX - dx);
- int[] region = hidden.getRegionWithEdgeAtRes(visx);
-
- if (region != null) // just in case
+ int maxHeight = av.getAlignment().getHeight();
+ SequenceI seqAtRow = av.getAlignment()
+ .getSequenceAt(seqCanvas.cursorY);
+ // look for next gap or residue
+ boolean isGap = Comparison
+ .isGap(seqAtRow.getCharAt(seqCanvas.cursorX));
+ int p = seqCanvas.cursorX, lastP, r = seqCanvas.cursorY, lastR;
+ do
+ {
+ lastP = p;
+ lastR = r;
+ if (dy != 0)
{
- if (dx == 1)
+ r += dy;
+ if (r < 0)
{
- // moving right
- seqCanvas.cursorX = region[1] + 1;
+ r = 0;
}
- else if (dx == -1)
+ if (r >= maxHeight)
{
- // moving left
- seqCanvas.cursorX = region[0] - 1;
+ r = maxHeight - 1;
}
+ seqAtRow = av.getAlignment().getSequenceAt(r);
}
- seqCanvas.cursorX = (seqCanvas.cursorX < 0) ? 0 : seqCanvas.cursorX;
- }
+ p = nextVisible(hidden, maxWidth, p, dx);
+ } while ((dx != 0 ? p != lastP : r != lastR)
+ && isGap == Comparison.isGap(seqAtRow.getCharAt(p)));
+ seqCanvas.cursorX = p;
+ seqCanvas.cursorY = r;
+ }
+ else
+ {
+ int maxWidth = av.getAlignment().getWidth();
+ seqCanvas.cursorX = nextVisible(hidden, maxWidth, seqCanvas.cursorX,
+ dx);
+ seqCanvas.cursorY += dy;
+ }
+ scrollToVisible(false);
+ }
+
+ private int nextVisible(HiddenColumns hidden, int maxWidth, int original,
+ int dx)
+ {
+ int newCursorX = original + dx;
+ if (av.hasHiddenColumns() && !hidden.isVisible(newCursorX))
+ {
+ int visx = hidden.absoluteToVisibleColumn(newCursorX - dx);
+ int[] region = hidden.getRegionWithEdgeAtRes(visx);
- if (seqCanvas.cursorX >= maxWidth
- || !hidden.isVisible(seqCanvas.cursorX))
+ if (region != null) // just in case
{
- seqCanvas.cursorX = original;
+ if (dx == 1)
+ {
+ // moving right
+ newCursorX = region[1] + 1;
+ }
+ else if (dx == -1)
+ {
+ // moving left
+ newCursorX = region[0] - 1;
+ }
}
}
-
- scrollToVisible(false);
+ newCursorX = (newCursorX < 0) ? 0 : newCursorX;
+ if (newCursorX >= maxWidth || !hidden.isVisible(newCursorX))
+ {
+ newCursorX = original;
+ }
+ return newCursorX;
}
/**
@@ -559,7 +659,7 @@ public class SeqPanel extends JPanel
if (av.getAlignment().getHiddenColumns().isVisible(seqCanvas.cursorX))
{
setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
- seqCanvas.cursorX, seqCanvas.cursorY);
+ seqCanvas.cursorX, seqCanvas.cursorY);
}
if (repaintNeeded)
@@ -568,7 +668,6 @@ public class SeqPanel extends JPanel
}
}
-
void setSelectionAreaAtCursor(boolean topLeft)
{
SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
@@ -822,7 +921,7 @@ public class SeqPanel extends JPanel
if (lastMessage == null || !lastMessage.equals(tmp))
{
- // System.err.println("mouseOver Sequence: "+tmp);
+ // jalview.bin.Console.errPrintln("mouseOver Sequence: "+tmp);
ssm.mouseOverSequence(sequence, index, pos, av);
}
lastMessage = tmp;
@@ -860,8 +959,8 @@ public class SeqPanel extends JPanel
ap.setToScrollComplementPanel(true);
}
- boolean noFastPaint = wasScrolled && av.getWrapAlignment();
- if (seqCanvas.highlightSearchResults(results, noFastPaint))
+ boolean fastPaint = !(wasScrolled && av.getWrapAlignment());
+ if (seqCanvas.highlightSearchResults(results, fastPaint))
{
setStatusMessage(results);
}
@@ -895,25 +994,25 @@ public class SeqPanel extends JPanel
AlignFrame af = Desktop.getAlignFrameFor(complement);
FeatureRendererModel fr2 = af.getFeatureRenderer();
- int j = results.getSize();
+ List
").append("... ").append("")
+ .append(MessageManager.formatMessage(
+ "label.features_not_shown", unshownFeatures))
+ .append("");
+ }
String textString = tooltipText.toString();
- if (lastTooltip == null || !lastTooltip.equals(textString))
+ if (!textString.equals(lastTooltip))
{
- String formattedTooltipText = JvSwingUtils.wrapTooltip(true,
- textString);
- setToolTipText(formattedTooltipText);
lastTooltip = textString;
+ lastFormattedTooltip = JvSwingUtils.wrapTooltip(true, textString);
+ setToolTipText(lastFormattedTooltip);
}
}
}
@@ -1105,6 +1215,7 @@ public class SeqPanel extends JPanel
final int column = pos.column;
final int rowIndex = pos.annotationIndex;
+ // TODO - get yOffset for annotation, too
if (column < 0 || !av.getWrapAlignment() || !av.isShowAnnotation()
|| rowIndex < 0)
{
@@ -1113,16 +1224,37 @@ public class SeqPanel extends JPanel
AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
String tooltip = AnnotationPanel.buildToolTip(anns[rowIndex], column,
- anns);
- setToolTipText(tooltip);
- lastTooltip = tooltip;
+ anns, 0, av, ap);
+ if (tooltip == null ? tooltip != lastTooltip
+ : !tooltip.equals(lastTooltip))
+ {
+ lastTooltip = tooltip;
+ lastFormattedTooltip = tooltip == null ? null
+ : JvSwingUtils.wrapTooltip(true, tooltip);
+ setToolTipText(lastFormattedTooltip);
+ }
String msg = AnnotationPanel.getStatusMessage(av.getAlignment(), column,
- anns[rowIndex]);
+ anns[rowIndex], 0, av);
ap.alignFrame.setStatus(msg);
}
- private Point lastp = null;
+ /*
+ * if Shift key is held down while moving the mouse,
+ * the tooltip location is not changed once shown
+ */
+ private Point lastTooltipLocation = null;
+
+ /*
+ * this flag is false for pixel moves within a residue,
+ * to reduce tooltip flicker
+ */
+ private boolean moveTooltip = true;
+
+ /*
+ * a dummy tooltip used to estimate where to position tooltips
+ */
+ private JToolTip tempTip = new JLabel().createToolTip();
/*
* (non-Javadoc)
@@ -1132,29 +1264,31 @@ public class SeqPanel extends JPanel
@Override
public Point getToolTipLocation(MouseEvent event)
{
- if (tooltipText == null || tooltipText.length() <= 6)
+ // BH 2018
+
+ if (lastTooltip == null || !moveTooltip)
{
- lastp = null;
return null;
}
- int x = event.getX();
- int w = getWidth();
- // switch sides when tooltip is too close to edge
- int wdth = (w - x < 200) ? -(w / 2) : 5;
- Point p = lastp;
- if (!event.isShiftDown() || p == null)
+ if (lastTooltipLocation != null && event.isShiftDown())
{
- p = new Point(event.getX() + wdth, event.getY() - 20);
- lastp = p;
+ return lastTooltipLocation;
}
- /*
- * TODO: try to set position so region is not obscured by tooltip
- */
- return p;
- }
- String lastTooltip;
+ int x = event.getX();
+ int y = event.getY();
+ int w = getWidth();
+
+ tempTip.setTipText(lastFormattedTooltip);
+ int tipWidth = (int) tempTip.getPreferredSize().getWidth();
+
+ // was x += (w - x < 200) ? -(w / 2) : 5;
+ x = (x + tipWidth < w ? x + 10 : w - tipWidth);
+ Point p = new Point(x, y + av.getCharHeight()); // BH 2018 was - 20?
+
+ return lastTooltipLocation = p;
+ }
/**
* set when the current UI interaction has resulted in a change that requires
@@ -1163,7 +1297,8 @@ public class SeqPanel extends JPanel
* changed, so selective redraws can be applied (ie. only structures, only
* overview, etc)
*/
- private boolean updateOverviewAndStructs = false; // TODO: refactor to avcontroller
+ private boolean updateOverviewAndStructs = false; // TODO: refactor to
+ // avcontroller
/**
* set if av.getSelectionGroup() refers to a group that is defined on the
@@ -1192,7 +1327,7 @@ public class SeqPanel extends JPanel
{
char sequenceChar = sequence.getCharAt(column);
int pos = sequence.findPosition(column);
- setStatusMessage(sequence, seqIndex, sequenceChar, pos);
+ setStatusMessage(sequence.getName(), seqIndex, sequenceChar, pos);
return pos;
}
@@ -1208,7 +1343,7 @@ public class SeqPanel extends JPanel
* Sequence 6 ID: O.niloticus.3 Nucleotide: Uracil (2)
*
*
- * @param sequence
+ * @param seqName
* @param seqIndex
* sequence position in the alignment (1..)
* @param sequenceChar
@@ -1216,7 +1351,7 @@ public class SeqPanel extends JPanel
* @param residuePos
* the sequence residue position (if not over a gap)
*/
- protected void setStatusMessage(SequenceI sequence, int seqIndex,
+ protected void setStatusMessage(String seqName, int seqIndex,
char sequenceChar, int residuePos)
{
StringBuilder text = new StringBuilder(32);
@@ -1225,8 +1360,7 @@ public class SeqPanel extends JPanel
* Sequence number (if known), and sequence name.
*/
String seqno = seqIndex == -1 ? "" : " " + (seqIndex + 1);
- text.append("Sequence").append(seqno).append(" ID: ")
- .append(sequence.getName());
+ text.append("Sequence").append(seqno).append(" ID: ").append(seqName);
String residue = null;
@@ -1271,7 +1405,8 @@ public class SeqPanel extends JPanel
{
return;
}
- SequenceI ds = al.getSequenceAt(sequenceIndex).getDatasetSequence();
+ SequenceI alignedSeq = al.getSequenceAt(sequenceIndex);
+ SequenceI ds = alignedSeq.getDatasetSequence();
for (SearchResultMatchI m : results.getResults())
{
SequenceI seq = m.getSequence();
@@ -1283,8 +1418,8 @@ public class SeqPanel extends JPanel
if (seq == ds)
{
int start = m.getStart();
- setStatusMessage(seq, sequenceIndex, seq.getCharAt(start - 1),
- start);
+ setStatusMessage(alignedSeq.getName(), sequenceIndex,
+ seq.getCharAt(start - 1), start);
return;
}
}
@@ -1484,12 +1619,12 @@ public class SeqPanel extends JPanel
String label = null;
if (groupEditing)
{
- message.append("Edit group:");
+ message.append("Edit group:");
label = MessageManager.getString("action.edit_group");
}
else
{
- message.append("Edit sequence: " + seq.getName());
+ message.append("Edit sequence: " + seq.getName());
label = seq.getName();
if (label.length() > 10)
{
@@ -1681,8 +1816,7 @@ public class SeqPanel extends JPanel
{
for (int j = 0; j < startres - editLastRes; j++)
{
- if (!Comparison
- .isGap(groupSeqs[g].getCharAt(fixedRight - j)))
+ if (!Comparison.isGap(groupSeqs[g].getCharAt(fixedRight - j)))
{
blank = false;
break;
@@ -2030,7 +2164,7 @@ public class SeqPanel extends JPanel
if (mouseDragging && scrollThread == null)
{
- scrollThread = new ScrollThread();
+ startScrolling(e.getPoint());
}
}
@@ -2049,7 +2183,7 @@ public class SeqPanel extends JPanel
return;
}
- if (evt.getClickCount() > 1)
+ if (evt.getClickCount() > 1 && av.isShowSequenceFeatures())
{
sg = av.getSelectionGroup();
if (sg != null && sg.getSize() == 1
@@ -2074,49 +2208,98 @@ public class SeqPanel extends JPanel
* highlight the first feature at the position on the alignment
*/
SearchResultsI highlight = new SearchResults();
- highlight.addResult(sequence, features.get(0).getBegin(), features
- .get(0).getEnd());
- seqCanvas.highlightSearchResults(highlight, false);
+ highlight.addResult(sequence, features.get(0).getBegin(),
+ features.get(0).getEnd());
+ seqCanvas.highlightSearchResults(highlight, true);
/*
- * open the Amend Features dialog; clear highlighting afterwards,
- * whether changes were made or not
+ * open the Amend Features dialog
*/
- List
+ *
+ * Note that this method may also be fired by scrolling with a gesture on a
+ * trackpad.
+ */
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
e.consume();
double wheelRotation = e.getPreciseWheelRotation();
+
+ /*
+ * scroll more for large (fast) mouse movements
+ */
+ int size = 1 + (int) Math.abs(wheelRotation);
+
if (wheelRotation > 0)
{
if (e.isShiftDown())
{
- av.getRanges().scrollRight(true);
-
+ /*
+ * scroll right
+ * stop trying to scroll right when limit is reached (saves
+ * expensive calls to Alignment.getWidth())
+ */
+ while (size-- > 0 && !ap.isScrolledFullyRight())
+ {
+ if (!av.getRanges().scrollRight(true))
+ {
+ break;
+ }
+ }
}
else
{
- av.getRanges().scrollUp(false);
+ /*
+ * scroll down
+ */
+ while (size-- > 0)
+ {
+ if (!av.getRanges().scrollUp(false))
+ {
+ break;
+ }
+ }
}
}
else if (wheelRotation < 0)
{
if (e.isShiftDown())
{
- av.getRanges().scrollRight(false);
+ /*
+ * scroll left
+ */
+ while (size-- > 0)
+ {
+ if (!av.getRanges().scrollRight(false))
+ {
+ break;
+ }
+ }
}
else
{
- av.getRanges().scrollUp(true);
+ /*
+ * scroll up
+ */
+ while (size-- > 0)
+ {
+ if (!av.getRanges().scrollUp(true))
+ {
+ break;
+ }
+ }
}
}
@@ -2168,22 +2351,22 @@ public class SeqPanel extends JPanel
}
}
- if (evt.isPopupTrigger()) // Mac: mousePressed
- {
- showPopupMenu(evt, pos);
- return;
- }
-
/*
* defer right-mouse click handling to mouseReleased on Windows
* (where isPopupTrigger() will answer true)
* NB isRightMouseButton is also true for Cmd-click on Mac
*/
- if (SwingUtilities.isRightMouseButton(evt) && !Platform.isAMac())
+ if (Platform.isWinRightButton(evt))
{
return;
}
+ if (evt.isPopupTrigger()) // Mac: mousePressed
+ {
+ showPopupMenu(evt, pos);
+ return;
+ }
+
if (av.cursorMode)
{
seqCanvas.cursorX = res;
@@ -2343,7 +2526,7 @@ public class SeqPanel extends JPanel
return;
}
- res = Math.min(res, av.getAlignment().getWidth()-1);
+ res = Math.min(res, av.getAlignment().getWidth() - 1);
if (stretchGroup.getEndRes() == res)
{
@@ -2476,29 +2659,73 @@ 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() && scrollThread == null)
{
scrollThread = new ScrollThread();
+ scrollThread.setMousePosition(mousePos);
+ if (Platform.isJS())
+ {
+ /*
+ * Javascript - run every 20ms until scrolling stopped
+ * or reaches the limit of scrollable alignment
+ */
+ 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)
+ {
+ // SeqPanel.stopScrolling called
+ t.stop();
+ }
+ }
+ });
+ t.start();
+ }
+ else
+ {
+ /*
+ * Java - run in a new thread
+ */
+ scrollThread.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
@@ -2506,12 +2733,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
*/
@@ -2525,7 +2754,7 @@ public class SeqPanel extends JPanel
*/
public void stopScrolling()
{
- threadRunning = false;
+ keepRunning = false;
}
/**
@@ -2536,48 +2765,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);
@@ -2585,6 +2778,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;
}
}
@@ -2652,7 +2899,7 @@ public class SeqPanel extends JPanel
{
if (av.getAlignment() == null)
{
- Cache.log.warn("alignviewport av SeqSetId=" + av.getSequenceSetId()
+ Console.warn("alignviewport av SeqSetId=" + av.getSequenceSetId()
+ " ViewId=" + av.getViewId()
+ " 's alignment is NULL! returning immediately.");
return;
@@ -2707,7 +2954,7 @@ public class SeqPanel extends JPanel
if (copycolsel && av.hasHiddenColumns()
&& (av.getAlignment().getHiddenColumns() == null))
{
- System.err.println("Bad things");
+ jalview.bin.Console.errPrintln("Bad things");
}
if (repaint) // always true!
{
@@ -2752,7 +2999,7 @@ public class SeqPanel extends JPanel
* Map sequence selection
*/
SequenceGroup sg = MappingUtils.mapSequenceGroup(seqsel, sourceAv, av);
- av.setSelectionGroup(sg);
+ av.setSelectionGroup(sg != null && sg.getSize() > 0 ? sg : null);
av.isSelectionGroupChanged(true);
/*
@@ -2777,6 +3024,8 @@ public class SeqPanel extends JPanel
* if hidden column selection has changed
*/
ap.paintAlignment(hiddenChanged, hiddenChanged);
+ // propagate any selection changes
+ PaintRefresher.Refresh(ap, av.getSequenceSetId());
return true;
}