X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fappletgui%2FSeqPanel.java;h=f0ec51ce57ab19bee297368ce6ec3152f12360ec;hb=fe654aee9b43fb9c9307830c277f1e63576826ae;hp=b89c435a337ca79ccb51635af5018e67dc2f94f4;hpb=c3d92b4b7a6cb00f9e596dbb7cd6c8508da5c252;p=jalview.git diff --git a/src/jalview/appletgui/SeqPanel.java b/src/jalview/appletgui/SeqPanel.java index b89c435..f0ec51c 100644 --- a/src/jalview/appletgui/SeqPanel.java +++ b/src/jalview/appletgui/SeqPanel.java @@ -54,6 +54,10 @@ import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.ListIterator; import java.util.Vector; public class SeqPanel extends Panel implements MouseMotionListener, @@ -228,7 +232,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, endEditing(); if (av.getWrapAlignment()) { - ap.scrollToWrappedVisible(seqCanvas.cursorX); + av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX); } else { @@ -236,17 +240,17 @@ public class SeqPanel extends Panel implements MouseMotionListener, HiddenColumns hidden = av.getAlignment().getHiddenColumns(); while (seqCanvas.cursorY < ranges.getStartSeq()) { - ap.scrollUp(true); + ranges.scrollUp(true); } while (seqCanvas.cursorY > ranges.getEndSeq()) { - ap.scrollUp(false); + ranges.scrollUp(false); } while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(ranges .getStartRes())) { - if (!ap.scrollRight(false)) + if (!ranges.scrollRight(false)) { break; } @@ -254,7 +258,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(ranges .getEndRes())) { - if (!ap.scrollRight(true)) + if (!ranges.scrollRight(true)) { break; } @@ -413,13 +417,13 @@ public class SeqPanel extends Panel implements MouseMotionListener, * * @param sequence * aligned sequence object - * @param res + * @param column * alignment column * @param seq * index of sequence in alignment - * @return position of res in sequence + * @return position of column in sequence or -1 if at gap */ - void setStatusMessage(SequenceI sequence, int res, int seq) + void setStatusMessage(SequenceI sequence, int column, int seq) { // TODO remove duplication of identical gui method StringBuilder text = new StringBuilder(32); @@ -430,7 +434,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, /* * Try to translate the display character to residue name (null for gap). */ - final String displayChar = String.valueOf(sequence.getCharAt(res)); + final String displayChar = String.valueOf(sequence.getCharAt(column)); if (av.getAlignment().isNucleotide()) { residue = ResidueProperties.nucleotideName.get(displayChar); @@ -453,7 +457,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, int pos = -1; if (residue != null) { - pos = sequence.findPosition(res); + pos = sequence.findPosition(column); text.append(" (").append(Integer.toString(pos)).append(")"); } @@ -563,20 +567,23 @@ public class SeqPanel extends Panel implements MouseMotionListener, av.setSelectionGroup(null); } - SequenceFeature[] features = findFeaturesAtRes(sequence, - sequence.findPosition(findRes(evt))); + int column = findRes(evt); + boolean isGapped = Comparison.isGap(sequence.getCharAt(column)); + List features = findFeaturesAtRes(sequence, + sequence.findPosition(column)); + if (isGapped) + { + removeAdjacentFeatures(features, column + 1, sequence); + } - if (features != null && features.length > 0) + if (!features.isEmpty()) { SearchResultsI highlight = new SearchResults(); - highlight.addResult(sequence, features[0].getBegin(), - features[0].getEnd()); + highlight.addResult(sequence, features.get(0).getBegin(), features + .get(0).getEnd()); seqCanvas.highlightSearchResults(highlight); - } - if (features != null && features.length > 0) - { seqCanvas.getFeatureRenderer().amendFeatures( - new SequenceI[] { sequence }, features, false, ap); + Collections.singletonList(sequence), features, false, ap); seqCanvas.highlightSearchResults(null); } @@ -586,13 +593,13 @@ public class SeqPanel extends Panel implements MouseMotionListener, @Override public void mouseReleased(MouseEvent evt) { + boolean didDrag = mouseDragging; // did we come here after a drag mouseDragging = false; mouseWheelPressed = false; - ap.paintAlignment(true); if (!editingSeqs) { - doMouseReleasedDefineMode(evt); + doMouseReleasedDefineMode(evt, didDrag); return; } @@ -747,10 +754,16 @@ public class SeqPanel extends Panel implements MouseMotionListener, { if (av.isFollowHighlight()) { + // don't allow highlight of protein/cDNA to also scroll a complementary + // panel,as this sets up a feedback loop (scrolling panel 1 causes moused + // over residue to change abruptly, causing highlighted residue in panel 2 + // to change, causing a scroll in panel 1 etc) + ap.setToScrollComplementPanel(false); if (ap.scrollToPosition(results, true)) { ap.alignFrame.repaint(); } + ap.setToScrollComplementPanel(true); } setStatusMessage(results); seqCanvas.highlightSearchResults(results); @@ -796,9 +809,11 @@ public class SeqPanel extends Panel implements MouseMotionListener, } final char ch = sequence.getCharAt(column); - int respos = Comparison.isGap(ch) ? -1 : sequence.findPosition(column); + boolean isGapped = Comparison.isGap(ch); + // find residue at column (or nearest if at a gap) + int respos = sequence.findPosition(column); - if (ssm != null && respos != -1) + if (ssm != null && !isGapped) { mouseOverSequence(sequence, column, respos); } @@ -807,30 +822,21 @@ public class SeqPanel extends Panel implements MouseMotionListener, text.append("Sequence ").append(Integer.toString(seq + 1)) .append(" ID: ").append(sequence.getName()); - String obj = null; - if (respos != -1) + if (!isGapped) { if (av.getAlignment().isNucleotide()) { - obj = ResidueProperties.nucleotideName.get(ch); - if (obj != null) - { - text.append(" Nucleotide: ").append(obj); - } + String base = ResidueProperties.nucleotideName.get(ch); + text.append(" Nucleotide: ").append(base == null ? ch : base); } else { - obj = (ch == 'x' || ch == 'X') ? "X" : ResidueProperties.aa2Triplet + String residue = (ch == 'x' || ch == 'X') ? "X" + : ResidueProperties.aa2Triplet .get(String.valueOf(ch)); - if (obj != null) - { - text.append(" Residue: ").append(obj); - } - } - if (obj != null) - { - text.append(" (").append(Integer.toString(respos)).append(")"); + text.append(" Residue: ").append(residue == null ? ch : residue); } + text.append(" (").append(Integer.toString(respos)).append(")"); } ap.alignFrame.statusBar.setText(text.toString()); @@ -858,18 +864,19 @@ public class SeqPanel extends Panel implements MouseMotionListener, } /* - * add feature details to tooltip if over one or more features + * add feature details to tooltip, including any that straddle + * a gapped position */ - if (respos != -1) + if (av.isShowSequenceFeatures()) { - SequenceFeature[] allFeatures = findFeaturesAtRes(sequence, + List allFeatures = findFeaturesAtRes(sequence, sequence.findPosition(column)); - - int index = 0; - while (index < allFeatures.length) + if (isGapped) + { + removeAdjacentFeatures(allFeatures, column + 1, sequence); + } + for (SequenceFeature sf : allFeatures) { - SequenceFeature sf = allFeatures[index]; - tooltipText.append(sf.getType() + " " + sf.begin + ":" + sf.end); if (sf.getDescription() != null) @@ -886,8 +893,6 @@ public class SeqPanel extends Panel implements MouseMotionListener, } } tooltipText.append("\n"); - - index++; } } @@ -901,9 +906,35 @@ public class SeqPanel extends Panel implements MouseMotionListener, } } - SequenceFeature[] findFeaturesAtRes(SequenceI sequence, int res) + /** + * Removes from the list of features any that start after, or end before, the + * given column position. This allows us to retain only those features + * adjacent to a gapped position that straddle the position. + * + * @param features + * @param column + * alignment column (1..) + * @param sequence + */ + protected void removeAdjacentFeatures(List features, + int column, SequenceI sequence) + { + // TODO should this be an AlignViewController method (shared by gui)? + ListIterator it = features.listIterator(); + while (it.hasNext()) + { + SequenceFeature sf = it.next(); + if (sequence.findIndex(sf.getBegin()) > column + || sequence.findIndex(sf.getEnd()) < column) + { + it.remove(); + } + } + } + + List findFeaturesAtRes(SequenceI sequence, int res) { - Vector tmp = new Vector(); + List result = new ArrayList(); SequenceFeature[] features = sequence.getSequenceFeatures(); if (features != null) { @@ -926,15 +957,12 @@ public class SeqPanel extends Panel implements MouseMotionListener, if ((features[i].getBegin() <= res) && (features[i].getEnd() >= res)) { - tmp.addElement(features[i]); + result.add(features[i]); } } } - features = new SequenceFeature[tmp.size()]; - tmp.copyInto(features); - - return features; + return result; } Tooltip tooltip; @@ -1460,24 +1488,21 @@ public class SeqPanel extends Panel implements MouseMotionListener, // DETECT RIGHT MOUSE BUTTON IN AWT if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) { - SequenceFeature[] allFeatures = findFeaturesAtRes(sequence, + List allFeatures = findFeaturesAtRes(sequence, sequence.findPosition(res)); Vector links = null; - if (allFeatures != null) + for (SequenceFeature sf : allFeatures) { - for (int i = 0; i < allFeatures.length; i++) + if (sf.links != null) { - if (allFeatures[i].links != null) + if (links == null) { - if (links == null) - { - links = new Vector(); - } - for (int j = 0; j < allFeatures[i].links.size(); j++) - { - links.addElement(allFeatures[i].links.elementAt(j)); - } + links = new Vector(); + } + for (int j = 0; j < sf.links.size(); j++) + { + links.addElement(sf.links.elementAt(j)); } } } @@ -1521,7 +1546,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, } } - public void doMouseReleasedDefineMode(MouseEvent evt) + public void doMouseReleasedDefineMode(MouseEvent evt, boolean afterDrag) { if (stretchGroup == null) { @@ -1531,7 +1556,8 @@ public class SeqPanel extends Panel implements MouseMotionListener, // but defer colourscheme update until hidden sequences are passed in boolean vischange = stretchGroup.recalcConservation(true); // here we rely on stretchGroup == av.getSelection() - needOverviewUpdate |= vischange && av.isSelectionDefinedGroup(); + needOverviewUpdate |= vischange && av.isSelectionDefinedGroup() + && afterDrag; if (stretchGroup.cs != null) { stretchGroup.cs.alignmentChanged(stretchGroup, @@ -1770,24 +1796,24 @@ public class SeqPanel extends Panel implements MouseMotionListener, if (mouseDragging && evt.getY() < 0 && av.getRanges().getStartSeq() > 0) { - running = ap.scrollUp(true); + running = av.getRanges().scrollUp(true); } if (mouseDragging && evt.getY() >= getSize().height && av.getAlignment().getHeight() > av.getRanges() .getEndSeq()) { - running = ap.scrollUp(false); + running = av.getRanges().scrollUp(false); } if (mouseDragging && evt.getX() < 0) { - running = ap.scrollRight(false); + running = av.getRanges().scrollRight(false); } else if (mouseDragging && evt.getX() >= getSize().width) { - running = ap.scrollRight(true); + running = av.getRanges().scrollRight(true); } }