X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fappletgui%2FSeqPanel.java;h=e4e3640a7885c544ed3f8884e71282c3d66e00b3;hb=b4d2b6a2ed131265ed599db27de9b82aaf010400;hp=14ea222758e1350968be62c3f21f6fd1012e917e;hpb=3f5e846ddfee0852718bef491e2839476f5281d3;p=jalview.git diff --git a/src/jalview/appletgui/SeqPanel.java b/src/jalview/appletgui/SeqPanel.java index 14ea222..e4e3640 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, @@ -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; } @@ -609,6 +616,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, int res = 0; int x = evt.getX(); + int startRes = av.getRanges().getStartRes(); if (av.getWrapAlignment()) { @@ -623,7 +631,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, int y = evt.getY(); y -= hgap; - x -= seqCanvas.LABEL_WEST; + x = Math.max(0, x - seqCanvas.LABEL_WEST); int cwidth = seqCanvas.getWrappedCanvasWidth(getSize().width); if (cwidth < 1) @@ -632,14 +640,15 @@ public class SeqPanel extends Panel implements MouseMotionListener, } wrappedBlock = y / cHeight; - wrappedBlock += av.getRanges().getStartRes() / cwidth; - - res = wrappedBlock * cwidth + x / av.getCharWidth(); - + wrappedBlock += startRes / cwidth; + int startOffset = startRes % cwidth; // in case start is scrolled right + // from 0 + res = wrappedBlock * cwidth + + Math.min(cwidth - 1, startOffset + x / av.getCharWidth()); } else { - res = (x / av.getCharWidth()) + av.getRanges().getStartRes(); + res = (x / av.getCharWidth()) + startRes; } if (av.hasHiddenColumns()) @@ -802,9 +811,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); } @@ -813,30 +824,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()); @@ -864,18 +866,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) @@ -892,8 +895,6 @@ public class SeqPanel extends Panel implements MouseMotionListener, } } tooltipText.append("\n"); - - index++; } } @@ -907,9 +908,38 @@ 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. Contact features + * that 'straddle' the position are also removed, since they are not 'at' 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 (sf.isContactFeature() + || 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) { @@ -932,15 +962,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; @@ -1466,24 +1493,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)); } } } @@ -1527,7 +1551,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, } } - public void doMouseReleasedDefineMode(MouseEvent evt) + public void doMouseReleasedDefineMode(MouseEvent evt, boolean afterDrag) { if (stretchGroup == null) { @@ -1537,7 +1561,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, @@ -1903,8 +1928,7 @@ public class SeqPanel extends Panel implements MouseMotionListener, } if (copycolsel && av.hasHiddenColumns() - && (av.getColumnSelection() == null || av.getAlignment() - .getHiddenColumns().getHiddenRegions() == null)) + && (av.getColumnSelection() == null)) { System.err.println("Bad things"); }