Merge branch 'develop' into features/JAL-2446NCList
[jalview.git] / src / jalview / appletgui / SeqPanel.java
index c57f88a..21eb6a4 100644 (file)
@@ -56,7 +56,6 @@ import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.util.Collections;
 import java.util.List;
-import java.util.ListIterator;
 import java.util.Vector;
 
 public class SeqPanel extends Panel implements MouseMotionListener,
@@ -530,7 +529,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
 
     int seq = findSeq(evt);
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (seq < 0 || res < 0)
     {
@@ -566,14 +565,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         av.setSelectionGroup(null);
       }
 
-      int column = findRes(evt);
-      boolean isGapped = Comparison.isGap(sequence.getCharAt(column));
-      List<SequenceFeature> features = findFeaturesAtRes(sequence,
-              sequence.findPosition(column));
-      if (isGapped)
-      {
-        removeAdjacentFeatures(features, column + 1, sequence);
-      }
+      int column = findColumn(evt);
+      List<SequenceFeature> features = findFeaturesAtColumn(sequence,
+              column + 1);
 
       if (!features.isEmpty())
       {
@@ -583,7 +577,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         seqCanvas.highlightSearchResults(highlight);
         seqCanvas.getFeatureRenderer().amendFeatures(
                 Collections.singletonList(sequence), features, false, ap);
-        seqCanvas.highlightSearchResults(null);
+        av.setSearchResults(null); // clear highlighting
+        seqCanvas.repaint(); // draw new/amended features
       }
     }
   }
@@ -609,11 +604,19 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
   int wrappedBlock = -1;
 
-  int findRes(MouseEvent evt)
+  /**
+   * Returns the aligned sequence position (base 0) at the mouse position, or
+   * the closest visible one
+   * 
+   * @param evt
+   * @return
+   */
+  int findColumn(MouseEvent evt)
   {
     int res = 0;
     int x = evt.getX();
 
+    int startRes = av.getRanges().getStartRes();
     if (av.getWrapAlignment())
     {
 
@@ -628,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)
@@ -637,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 + startOffset
+              + +Math.min(cwidth - 1, x / av.getCharWidth());
     }
     else
     {
-      res = (x / av.getCharWidth()) + av.getRanges().getStartRes();
+      res = (x / av.getCharWidth()) + startRes;
     }
 
     if (av.hasHiddenColumns())
@@ -712,7 +716,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
 
     int seq = findSeq(evt);
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (seq < av.getAlignment().getHeight()
             && res < av.getAlignment().getSequenceAt(seq).getLength())
@@ -784,7 +788,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   @Override
   public void mouseMoved(MouseEvent evt)
   {
-    final int column = findRes(evt);
+    final int column = findColumn(evt);
     int seq = findSeq(evt);
 
     if (seq >= av.getAlignment().getHeight() || seq < 0 || column < 0)
@@ -867,12 +871,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
      */
     if (av.isShowSequenceFeatures())
     {
-      List<SequenceFeature> allFeatures = findFeaturesAtRes(sequence,
-              respos);
-      if (isGapped)
-      {
-        removeAdjacentFeatures(allFeatures, column + 1, sequence);
-      }
+      List<SequenceFeature> allFeatures = findFeaturesAtColumn(sequence,
+              column + 1);
       for (SequenceFeature sf : allFeatures)
       {
         tooltipText.append(sf.getType() + " " + sf.begin + ":" + sf.end);
@@ -904,35 +904,19 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
   }
 
-  List<SequenceFeature> findFeaturesAtRes(SequenceI sequence, int res)
-  {
-    return seqCanvas.getFeatureRenderer().findFeaturesAtRes(sequence, 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.
+   * Returns features at the specified aligned column on the given sequence.
+   * Non-positional features are not included. If the column has a gap, then
+   * enclosing features are included (but not contact features).
    * 
-   * @param features
-   * @param column
-   *          alignment column (1..)
    * @param sequence
+   * @param column
+   *          (1..)
+   * @return
    */
-  protected void removeAdjacentFeatures(List<SequenceFeature> features,
-          int column, SequenceI sequence)
+  List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column)
   {
-    // TODO should this be an AlignViewController method (shared by gui)?
-    ListIterator<SequenceFeature> it = features.listIterator();
-    while (it.hasNext())
-    {
-      SequenceFeature sf = it.next();
-      if (sequence.findIndex(sf.getBegin()) > column
-              || sequence.findIndex(sf.getEnd()) < column)
-      {
-        it.remove();
-      }
-    }
+    return seqCanvas.getFeatureRenderer().findFeaturesAtColumn(sequence, column);
   }
 
   Tooltip tooltip;
@@ -1012,7 +996,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       return;
     }
 
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (res < 0)
     {
@@ -1194,7 +1178,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         // Find the next gap before the end
         // of the visible region boundary
         boolean blank = false;
-        for (fixedRight = fixedRight; fixedRight > lastres; fixedRight--)
+        for (; fixedRight > lastres; fixedRight--)
         {
           blank = true;
 
@@ -1425,7 +1409,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       scrollThread = null;
     }
 
-    int res = findRes(evt);
+    int column = findColumn(evt);
     int seq = findSeq(evt);
     oldSeq = seq;
     startWrapBlock = wrappedBlock;
@@ -1437,16 +1421,16 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 
-    if (sequence == null || res > sequence.getLength())
+    if (sequence == null || column > sequence.getLength())
     {
       return;
     }
 
     stretchGroup = av.getSelectionGroup();
 
-    if (stretchGroup == null || !stretchGroup.contains(sequence, res))
+    if (stretchGroup == null || !stretchGroup.contains(sequence, column))
     {
-      stretchGroup = av.getAlignment().findGroup(sequence, res);
+      stretchGroup = av.getAlignment().findGroup(sequence, column);
       if (stretchGroup != null)
       {
         // only update the current selection if the popup menu has a group to
@@ -1458,8 +1442,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     // DETECT RIGHT MOUSE BUTTON IN AWT
     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
-      List<SequenceFeature> allFeatures = findFeaturesAtRes(sequence,
-              sequence.findPosition(res));
+      List<SequenceFeature> allFeatures = findFeaturesAtColumn(sequence,
+              sequence.findPosition(column + 1));
 
       Vector<String> links = null;
       for (SequenceFeature sf : allFeatures)
@@ -1481,7 +1465,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     if (av.cursorMode)
     {
-      seqCanvas.cursorX = findRes(evt);
+      seqCanvas.cursorX = findColumn(evt);
       seqCanvas.cursorY = findSeq(evt);
       seqCanvas.repaint();
       return;
@@ -1493,8 +1477,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     {
       // define a new group here
       SequenceGroup sg = new SequenceGroup();
-      sg.setStartRes(res);
-      sg.setEndRes(res);
+      sg.setStartRes(column);
+      sg.setEndRes(column);
       sg.addSequence(sequence, false);
       av.setSelectionGroup(sg);
       stretchGroup = sg;
@@ -1552,7 +1536,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
   public void doMouseDraggedDefineMode(MouseEvent evt)
   {
-    int res = findRes(evt);
+    int res = findColumn(evt);
     int y = findSeq(evt);
 
     if (wrappedBlock != startWrapBlock)
@@ -1890,8 +1874,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");
     }