Merge branch 'merge/JAL-3609_and_JAL-3608' into releases/Release_2_11_1_Branch
authorJim Procter <jprocter@issues.jalview.org>
Sat, 4 Jul 2020 14:11:45 +0000 (15:11 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Sat, 4 Jul 2020 14:11:45 +0000 (15:11 +0100)
RELEASE
help/help/html/keys.html
help/help/html/releases.html
src/jalview/gui/AlignFrame.java
src/jalview/gui/SeqPanel.java
test/jalview/gui/SeqCanvasTest.java

diff --git a/RELEASE b/RELEASE
index 5a89907..3600be2 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,2 +1,2 @@
 jalview.release=releases/Release_2_11_1_Branch
-jalview.version=2.11.1.0
+jalview.version=2.11.1.1
index 1a5fc18..5f24a83 100755 (executable)
     </tr>
     <tr>
       <td><strong>Up Arrow</strong></td>
-      <td>Normal</td>
-      <td>Moves selected sequence(s) up the alignment</td>
+      <td>Both</td>
+      <td>Moves selected sequence(s) up the alignment.<br />In
+        Cursor mode press Alt key to move selection or sequence under
+        cursor.
+      </td>
     </tr>
     <tr>
       <td><strong>Down Arrow</strong></td>
-      <td>Normal</td>
-      <td>Moves selected sequence(s) down the alignment.</td>
+      <td>Both</td>
+      <td>Moves selected sequence(s) down the alignment.<br />In
+        Cursor mode press Alt key to move selection or sequence under
+        cursor.
+      </td>
     </tr>
     <tr>
       <td><strong>Left Arrow</strong></td>
       <td><strong>Cursor Keys<br> (Arrow Keys)
       </strong></td>
       <td>Cursor</td>
-      <td>Move cursor around alignment</td>
+      <td>Move cursor around alignment.<br /> Press SHIFT to move
+        cursor from an aligned region to next gap, or to the next
+        aligned region when at a gap.
+      </td>
     </tr>
     <tr>
       <td><strong>Page Up</strong></td>
index 5b6180d..83a9cc3 100755 (executable)
@@ -57,6 +57,37 @@ li:before {
     </tr>
     <tr>
       <td width="60" align="center" nowrap><strong><a
+          id="Jalview.2.11.1">2.11.1</a><a id="Jalview.2.11.1.1">.1</a><br />
+          <em>13/07/2020</em></strong></td>
+      <td align="left" valign="top">
+        <ul>
+          <!-- -->
+          <li>
+            <!-- JAL-3638 -->Shift+arrow keys navigate to next gap or
+            residue in cursor mode
+          </li>
+          <li></li>
+        </ul>
+      </td>
+      <td align="left" valign="top">
+        <ul>
+          <li>
+            <!-- JAL-3493 -->Escape does not clear highlights on the
+            alignment (Since Jalview 2.10.3)
+          </li>
+          <li>
+            <!--  JAL-3680 -->Alt+Left or Right arrow in cursor mode
+            doesn't slide selected sequences
+          </li>
+          <li>
+            <!-- JAL-3613 -->Peptide-to-CDS tracking broken when
+            multiple EMBL gene products shown forĀ a single contig
+          </li>
+        </ul>
+      </td>
+    </tr>
+    <tr>
+      <td width="60" align="center" nowrap><strong><a
           id="Jalview.2.11.1">2.11.1</a><a id="Jalview.2.11.1.0">.0</a><br />
           <em>22/04/2020</em></strong></td>
       <td align="left" valign="top">
index b7d8b3a..d03b2c7 100644 (file)
@@ -536,7 +536,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
           if (viewport.cursorMode)
           {
-            alignPanel.getSeqPanel().moveCursor(0, 1);
+            alignPanel.getSeqPanel().moveCursor(0, 1,
+                    evt.isShiftDown() && !evt.isAltDown());
           }
           break;
 
@@ -547,9 +548,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
           if (viewport.cursorMode)
           {
-            alignPanel.getSeqPanel().moveCursor(0, -1);
+            alignPanel.getSeqPanel().moveCursor(0, -1,
+                    evt.isShiftDown() && !evt.isAltDown());
           }
-
           break;
 
         case KeyEvent.VK_LEFT:
@@ -560,7 +561,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
           else
           {
-            alignPanel.getSeqPanel().moveCursor(-1, 0);
+            alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
           }
 
           break;
@@ -572,7 +573,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           }
           else
           {
-            alignPanel.getSeqPanel().moveCursor(1, 0);
+            alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
           }
           break;
 
@@ -1740,19 +1741,19 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   synchronized void slideSequences(boolean right, int size)
   {
     List<SequenceI> sg = new ArrayList<>();
-    if (viewport.cursorMode)
-    {
-      sg.add(viewport.getAlignment()
-              .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
-    }
-    else if (viewport.getSelectionGroup() != null
-            && viewport.getSelectionGroup().getSize() != viewport
-                    .getAlignment().getHeight())
+    if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup()
+            .getSize() != viewport.getAlignment().getHeight())
     {
       sg = viewport.getSelectionGroup()
               .getSequences(viewport.getHiddenRepSequences());
     }
 
+    if (sg.size() == 0 && viewport.cursorMode)
+    {
+      sg.add(viewport.getAlignment()
+              .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
+    }
+
     if (sg.size() < 1)
     {
       return;
@@ -2450,7 +2451,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     viewport.setSelectionGroup(null);
     viewport.getColumnSelection().clear();
-    viewport.setSelectionGroup(null);
+    viewport.setSearchResults(null);
     alignPanel.getIdPanel().getIdCanvas().searchResults = null;
     // JAL-2034 - should delegate to
     // alignPanel to decide if overview needs
index def4be1..407acd6 100644 (file)
@@ -460,47 +460,80 @@ 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);
+  }
 
-      if (seqCanvas.cursorX >= maxWidth
-              || !hidden.isVisible(seqCanvas.cursorX))
+  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 (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;
   }
-
   /**
    * Scroll to make the cursor visible in the viewport.
    * 
index 73aeb79..213a1c9 100644 (file)
 package jalview.gui;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
 
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
 
@@ -338,4 +344,27 @@ public class SeqCanvasTest
             "wrappedRepeatHeightPx");
     assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
   }
+
+  @Test(groups = "Functional")
+  public void testClear_HighlightAndSelection()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = af.getViewport();
+    SearchResultsI highlight = new SearchResults();
+    highlight.addResult(
+            av.getAlignment().getSequenceAt(1).getDatasetSequence(), 50,
+            80);
+    af.alignPanel.highlightSearchResults(highlight);
+    af.avc.markHighlightedColumns(false, false, false);
+    assertNotNull(av.getSearchResults(),
+            "No highlight was created on alignment");
+    assertFalse(av.getColumnSelection().isEmpty(),
+            "No selection was created from highlight");
+    af.deselectAllSequenceMenuItem_actionPerformed(null);
+    assertTrue(av.getColumnSelection().isEmpty(),
+            "No Selection should be present after deselecting all.");
+    assertNull(av.getSearchResults(),
+            "No higlighted search results should be present after deselecting all.");
+  }
 }