JAL-2349 JAL-4033 refactored contact matrix geom calc to allow reporting of mapped...
[jalview.git] / src / jalview / gui / SeqPanel.java
index 8a49092..6918811 100644 (file)
@@ -44,7 +44,7 @@ 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;
@@ -246,8 +246,7 @@ public class SeqPanel extends JPanel
     ToolTipManager.sharedInstance().registerComponent(this);
     ToolTipManager.sharedInstance().setInitialDelay(0);
     ToolTipManager.sharedInstance().setDismissDelay(10000);
-    
-    
+
     this.av = viewport;
     setBackground(Color.white);
 
@@ -275,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
+   * <p>
+   * 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
@@ -339,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
+   * <p>
+   * Returns -1 if in wrapped mode with the mouse over either left or right
+   * vertical scale.
    * 
    * @param evt
    * @return
@@ -477,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;
   }
 
   /**
@@ -573,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)
@@ -582,7 +628,6 @@ public class SeqPanel extends JPanel
     }
   }
 
-
   void setSelectionAreaAtCursor(boolean topLeft)
   {
     SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
@@ -909,19 +954,19 @@ public class SeqPanel extends JPanel
     AlignFrame af = Desktop.getAlignFrameFor(complement);
     FeatureRendererModel fr2 = af.getFeatureRenderer();
 
-    int j = results.getSize();
+    List<SearchResultMatchI> matches = results.getResults();
+    int j = matches.size();
     List<String> 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)
         {
           for (SequenceFeature sf : mf.features)
@@ -1064,9 +1109,8 @@ public class SeqPanel extends JPanel
     {
       List<SequenceFeature> features = ap.getFeatureRenderer()
               .findFeaturesAtColumn(sequence, column + 1);
-      unshownFeatures = seqARep.appendFeatures(tooltipText, pos,
-              features, this.ap.getSeqPanel().seqCanvas.fr,
-              MAX_TOOLTIP_LENGTH);
+      unshownFeatures = seqARep.appendFeatures(tooltipText, pos, features,
+              this.ap.getSeqPanel().seqCanvas.fr, MAX_TOOLTIP_LENGTH);
 
       /*
        * add features in CDS/protein complement at the corresponding
@@ -1084,8 +1128,8 @@ public class SeqPanel extends JPanel
                   pos);
           if (mf != null)
           {
-            unshownFeatures += seqARep.appendFeatures(tooltipText,
-                    pos, mf, fr2, MAX_TOOLTIP_LENGTH);
+            unshownFeatures += seqARep.appendFeatures(tooltipText, pos, mf,
+                    fr2, MAX_TOOLTIP_LENGTH);
           }
         }
       }
@@ -1113,8 +1157,7 @@ public class SeqPanel extends JPanel
       if (!textString.equals(lastTooltip))
       {
         lastTooltip = textString;
-        lastFormattedTooltip = JvSwingUtils.wrapTooltip(true,
-                textString);
+        lastFormattedTooltip = JvSwingUtils.wrapTooltip(true, textString);
         setToolTipText(lastFormattedTooltip);
       }
     }
@@ -1132,6 +1175,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)
     {
@@ -1140,8 +1184,9 @@ public class SeqPanel extends JPanel
     AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
 
     String tooltip = AnnotationPanel.buildToolTip(anns[rowIndex], column,
-            anns);
-    if (!tooltip.equals(lastTooltip))
+            anns, 0, av);
+    if (tooltip == null ? tooltip != lastTooltip
+            : !tooltip.equals(lastTooltip))
     {
       lastTooltip = tooltip;
       lastFormattedTooltip = tooltip == null ? null
@@ -1150,7 +1195,7 @@ public class SeqPanel extends JPanel
     }
 
     String msg = AnnotationPanel.getStatusMessage(av.getAlignment(), column,
-            anns[rowIndex]);
+            anns[rowIndex], 0, av);
     ap.alignFrame.setStatus(msg);
   }
 
@@ -1197,8 +1242,8 @@ public class SeqPanel extends JPanel
 
     tempTip.setTipText(lastFormattedTooltip);
     int tipWidth = (int) tempTip.getPreferredSize().getWidth();
-    
-    // was      x += (w - x < 200) ? -(w / 2) : 5;
+
+    // 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?
 
@@ -1212,7 +1257,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
@@ -1274,8 +1320,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(seqName);
+    text.append("Sequence").append(seqno).append(" ID: ").append(seqName);
 
     String residue = null;
 
@@ -1534,12 +1579,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)
       {
@@ -1731,8 +1776,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;
@@ -2124,8 +2168,8 @@ 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());
+        highlight.addResult(sequence, features.get(0).getBegin(),
+                features.get(0).getEnd());
         seqCanvas.highlightSearchResults(highlight, true);
 
         /*
@@ -2389,7 +2433,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)
     {
@@ -2762,7 +2806,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;