X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FSeqPanel.java;h=111b4c0112b6fec9a47ad37b7a90535fbb99f171;hb=ea7aa18440e6140ec7485e6cefdfb1dffb945580;hp=bc17cc22182c203b40cf0ff17cdc3b8dd08beb53;hpb=74393b51f368cb9f58589472d432a433d9c4386d;p=jalview.git diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index bc17cc2..111b4c0 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! * @@ -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,9 +341,13 @@ public class SeqPanel extends JPanel return new MousePos(col, seqIndex, annIndex); } + /** * 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 @@ -463,45 +483,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 +619,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 +628,6 @@ public class SeqPanel extends JPanel } } - void setSelectionAreaAtCursor(boolean topLeft) { SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY); @@ -860,8 +919,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,27 +954,27 @@ public class SeqPanel extends JPanel AlignFrame af = Desktop.getAlignFrameFor(complement); FeatureRendererModel fr2 = af.getFeatureRenderer(); - int j = results.getSize(); + List matches = results.getResults(); + int j = matches.size(); List infos = new ArrayList<>(); for (int i = 0; i < j; i++) { - SearchResultMatchI match = results.getResults().get(i); + SearchResultMatchI match = matches.get(i); int pos = match.getStart(); if (pos == match.getEnd()) { SequenceI seq = match.getSequence(); SequenceI ds = seq.getDatasetSequence() == null ? seq : seq.getDatasetSequence(); - MappedFeatures mf = fr2 - .findComplementFeaturesAtResidue(ds, pos); + MappedFeatures mf = fr2.findComplementFeaturesAtResidue(ds, pos); if (mf != null) { - List pv = mf.findProteinVariants(); - for (String s : pv) + for (SequenceFeature sf : mf.features) { - if (!infos.contains(s)) + String pv = mf.findProteinVariants(sf); + if (pv.length() > 0 && !infos.contains(pv)) { - infos.addAll(pv); + infos.add(pv); } } } @@ -975,8 +1034,10 @@ public class SeqPanel extends JPanel /* * just a pixel move without change of 'cell' */ + moveTooltip = false; return; } + moveTooltip = true; lastMousePosition = mousePos; if (mousePos.isOverAnnotation()) @@ -992,6 +1053,7 @@ public class SeqPanel extends JPanel lastMousePosition = null; setToolTipText(null); lastTooltip = null; + lastFormattedTooltip = null; ap.alignFrame.setStatus(""); return; } @@ -1013,7 +1075,7 @@ public class SeqPanel extends JPanel mouseOverSequence(sequence, column, pos); } - tooltipText.setLength(6); // Cuts the buffer back to + StringBuilder tooltipText = new StringBuilder(64); SequenceGroup[] groups = av.getAlignment().findAllGroups(sequence); if (groups != null) @@ -1042,12 +1104,13 @@ public class SeqPanel extends JPanel * add features that straddle the gap (pos may be the residue before or * after the gap) */ + int unshownFeatures = 0; if (av.isShowSequenceFeatures()) { List features = ap.getFeatureRenderer() .findFeaturesAtColumn(sequence, column + 1); - seqARep.appendFeatures(tooltipText, pos, features, - this.ap.getSeqPanel().seqCanvas.fr); + unshownFeatures = seqARep.appendFeatures(tooltipText, pos, features, + this.ap.getSeqPanel().seqCanvas.fr, MAX_TOOLTIP_LENGTH); /* * add features in CDS/protein complement at the corresponding @@ -1065,30 +1128,37 @@ public class SeqPanel extends JPanel pos); if (mf != null) { - seqARep.appendFeatures(tooltipText, pos, mf.features, fr2); + unshownFeatures += seqARep.appendFeatures(tooltipText, pos, mf, + fr2, MAX_TOOLTIP_LENGTH); } } } } - if (tooltipText.length() == 6) // + if (tooltipText.length() == 0) // nothing added { setToolTipText(null); lastTooltip = null; } else { - if (tooltipText.length() > MAX_TOOLTIP_LENGTH) // constant + if (tooltipText.length() > MAX_TOOLTIP_LENGTH) { tooltipText.setLength(MAX_TOOLTIP_LENGTH); tooltipText.append("..."); } + if (unshownFeatures > 0) + { + tooltipText.append("
").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); } } } @@ -1114,15 +1184,36 @@ public class SeqPanel extends JPanel String tooltip = AnnotationPanel.buildToolTip(anns[rowIndex], column, anns); - setToolTipText(tooltip); - lastTooltip = tooltip; + 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]); 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 +1223,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 +1256,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 +1286,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 +1302,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 +1310,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 +1319,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 +1364,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 +1377,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 +1578,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 +1775,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 +2123,7 @@ public class SeqPanel extends JPanel if (mouseDragging && scrollThread == null) { - scrollThread = new ScrollThread(); + startScrolling(e.getPoint()); } } @@ -2049,7 +2142,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,19 +2167,15 @@ 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 seqs = Collections.singletonList(sequence); - seqCanvas.getFeatureRenderer().amendFeatures(seqs, features, false, - ap); - av.setSearchResults(null); // clear highlighting - seqCanvas.repaint(); // draw new/amended features + new FeatureEditor(ap, Collections.singletonList(sequence), features, + false).showDialog(); } } } @@ -2168,22 +2257,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; @@ -2254,11 +2343,11 @@ public class SeqPanel extends JPanel final int column = pos.column; final int seq = pos.seqIndex; SequenceI sequence = av.getAlignment().getSequenceAt(seq); - List features = ap.getFeatureRenderer() - .findFeaturesAtColumn(sequence, column + 1); - - PopupMenu pop = new PopupMenu(ap, null, features); - pop.show(this, evt.getX(), evt.getY()); + if (sequence != null) + { + PopupMenu pop = new PopupMenu(ap, sequence, column); + pop.show(this, evt.getX(), evt.getY()); + } } /** @@ -2343,7 +2432,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 +2565,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 +2639,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 +2660,7 @@ public class SeqPanel extends JPanel */ public void stopScrolling() { - threadRunning = false; + keepRunning = false; } /** @@ -2536,48 +2671,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 +2684,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 +2805,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; @@ -2752,7 +2905,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); /*