jalview.release=releases/Release_2_11_1_Branch
-jalview.version=2.11.1.0
+jalview.version=2.11.1.1
</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>
</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">
}
if (viewport.cursorMode)
{
- alignPanel.getSeqPanel().moveCursor(0, 1);
+ alignPanel.getSeqPanel().moveCursor(0, 1,
+ evt.isShiftDown() && !evt.isAltDown());
}
break;
}
if (viewport.cursorMode)
{
- alignPanel.getSeqPanel().moveCursor(0, -1);
+ alignPanel.getSeqPanel().moveCursor(0, -1,
+ evt.isShiftDown() && !evt.isAltDown());
}
-
break;
case KeyEvent.VK_LEFT:
}
else
{
- alignPanel.getSeqPanel().moveCursor(-1, 0);
+ alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
}
break;
}
else
{
- alignPanel.getSeqPanel().moveCursor(1, 0);
+ alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
}
break;
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;
}
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
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.
*
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;
"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.");
+ }
}