<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
<classpathentry kind="lib" path="lib/biojava-core-4.1.0.jar"/>
<classpathentry kind="lib" path="lib/biojava-ontology-4.1.0.jar"/>
- <classpathentry kind="lib" path="lib/groovy-all-2.4.6-indy.jar"/>
+ <classpathentry kind="lib" path="lib/groovy-all-2.4.12-indy.jar"/>
<classpathentry kind="output" path="classes"/>
</classpath>
To set up benchmarking:
-1. In the jalview directory run
+You will need to install Maven: https://maven.apache.org/install.html
+
+1. Run the makedist target of build.xml in Eclipse, or in the jalview directory run
ant makedist
This builds a jalview.jar file and puts it into dist/
-2. Make a lib directory in benchmarking/ if not already present.
+2. Make a lib directory in benchmarking/ if not already present and cd into this directory.
3. Purge any previous maven dependencies:
mvn dependency:purge-local-repository -DactTransitively=false -DreResolve=false
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Fork(1)
public class HiddenColumnsBenchmark
-{
- /*
- * State with multiple hidden columns and a start position set
- */
- @State(Scope.Thread)
- public static class HiddenColsAndStartState
- {
- @Param({"300", "10000", "100000"})
- public int maxcols;
-
- @Param({"1", "50", "90"})
- public int startpcnt; // position as percentage of maxcols
-
- @Param({"1","15","100"})
- public int hide;
-
- HiddenColumns h = new HiddenColumns();
- Random rand = new Random();
-
- public int hiddenColumn;
- public int visibleColumn;
-
- @Setup
- public void setup()
- {
- rand.setSeed(1234);
- int lastcol = 0;
- while (lastcol < maxcols)
- {
- int count = rand.nextInt(100);
- lastcol += count;
- h.hideColumns(lastcol, lastcol+hide);
- lastcol+=hide;
- }
-
- // make sure column at start is hidden
- hiddenColumn = (int)(maxcols * startpcnt/100.0);
- h.hideColumns(hiddenColumn, hiddenColumn);
-
- // and column <hide> after start is visible
- ColumnSelection sel = new ColumnSelection();
- h.revealHiddenColumns(hiddenColumn+hide, sel);
- visibleColumn = hiddenColumn+hide;
-
- System.out.println("Maxcols: " + maxcols + " HiddenCol: " + hiddenColumn + " Hide: " + hide);
- System.out.println("Number of hidden columns: " + h.getSize());
- }
- }
-
- /* Convention: functions in alphabetical order */
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public int benchAdjustForHiddenColumns(HiddenColsAndStartState tstate)
- {
- return tstate.h.adjustForHiddenColumns(tstate.visibleColumn);
- }
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public int benchFindColumnPosition(HiddenColsAndStartState tstate)
- {
- return tstate.h.findColumnPosition(tstate.visibleColumn);
- }
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public List<Integer> benchFindHiddenRegionPositions(HiddenColsAndStartState tstate)
- {
- return tstate.h.findHiddenRegionPositions();
- }
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public ArrayList<int[]> benchGetHiddenColumnsCopy(HiddenColsAndStartState tstate)
- {
- return tstate.h.getHiddenColumnsCopy();
- }
-
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public int benchGetSize(HiddenColsAndStartState tstate)
- {
- return tstate.h.getSize();
- }
+{
+ /*
+ * State with multiple hidden columns and a start position set
+ */
+ @State(Scope.Thread)
+ public static class HiddenColsAndStartState
+ {
+ @Param({ "300", "10000", "100000" })
+ public int maxcols;
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public HiddenColumns benchHideCols(HiddenColsAndStartState tstate)
- {
- tstate.h.hideColumns(tstate.visibleColumn,
- tstate.visibleColumn+2000);
- return tstate.h;
- }
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public boolean benchIsVisible(HiddenColsAndStartState tstate)
- {
- return tstate.h.isVisible(tstate.hiddenColumn);
- }
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public HiddenColumns benchReveal(HiddenColsAndStartState tstate)
- {
- ColumnSelection sel = new ColumnSelection();
- tstate.h.revealHiddenColumns(tstate.hiddenColumn, sel);
- return tstate.h;
- }
-
- @Benchmark
- @BenchmarkMode({Mode.Throughput})
- public HiddenColumns benchRevealAll(HiddenColsAndStartState tstate)
+ @Param({ "1", "50", "90" })
+ public int startpcnt; // position as percentage of maxcols
+
+ @Param({ "1", "15", "100" })
+ public int hide;
+
+ HiddenColumns h = new HiddenColumns();
+
+ Random rand = new Random();
+
+ public int hiddenColumn;
+
+ public int visibleColumn;
+
+ @Setup
+ public void setup()
{
- ColumnSelection sel = new ColumnSelection();
- tstate.h.revealAllHiddenColumns(sel);
- return tstate.h;
+ rand.setSeed(1234);
+ int lastcol = 0;
+ while (lastcol < maxcols)
+ {
+ int count = rand.nextInt(100);
+ lastcol += count;
+ h.hideColumns(lastcol, lastcol + hide);
+ lastcol += hide;
+ }
+
+ // make sure column at start is hidden
+ hiddenColumn = (int) (maxcols * startpcnt / 100.0);
+ h.hideColumns(hiddenColumn, hiddenColumn);
+
+ // and column <hide> after start is visible
+ ColumnSelection sel = new ColumnSelection();
+ h.revealHiddenColumns(hiddenColumn + hide, sel);
+ visibleColumn = hiddenColumn + hide;
+
+ System.out.println("Maxcols: " + maxcols + " HiddenCol: "
+ + hiddenColumn + " Hide: " + hide);
+ System.out.println("Number of hidden columns: " + h.getSize());
}
-
-
+ }
+
+ /* Convention: functions in alphabetical order */
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public int benchAdjustForHiddenColumns(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.adjustForHiddenColumns(tstate.visibleColumn);
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public int benchFindColumnPosition(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.findColumnPosition(tstate.visibleColumn);
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public List<Integer> benchFindHiddenRegionPositions(
+ HiddenColsAndStartState tstate)
+ {
+ return tstate.h.findHiddenRegionPositions();
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public ArrayList<int[]> benchGetHiddenColumnsCopy(
+ HiddenColsAndStartState tstate)
+ {
+ return tstate.h.getHiddenColumnsCopy();
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public int benchGetSize(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.getSize();
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public HiddenColumns benchHideCols(HiddenColsAndStartState tstate)
+ {
+ tstate.h.hideColumns(tstate.visibleColumn, tstate.visibleColumn + 2000);
+ return tstate.h;
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public boolean benchIsVisible(HiddenColsAndStartState tstate)
+ {
+ return tstate.h.isVisible(tstate.hiddenColumn);
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public HiddenColumns benchReveal(HiddenColsAndStartState tstate)
+ {
+ ColumnSelection sel = new ColumnSelection();
+ tstate.h.revealHiddenColumns(tstate.hiddenColumn, sel);
+ return tstate.h;
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.Throughput })
+ public HiddenColumns benchRevealAll(HiddenColsAndStartState tstate)
+ {
+ ColumnSelection sel = new ColumnSelection();
+ tstate.h.revealAllHiddenColumns(sel);
+ return tstate.h;
+ }
+
}
\ No newline at end of file
<jnlpf toFile="${jnlpFile}" />
<!-- add the add-modules j2se attribute for java 9 -->
- <replace file="${jnlpFile}" value="j2se version="1.7+" initial-heap-size="${inih}" max-heap-size="${maxh}" java-vm-args="--add-modules=java.se.ee"">
+ <replace file="${jnlpFile}" value="j2se version="1.7+" initial-heap-size="${inih}" max-heap-size="${maxh}" java-vm-args="--add-modules=java.se.ee --illegal-access=warn"">
<replacetoken>j2se version="1.7+"</replacetoken>
</replace>
<tocitem text="Jalview Documentation" target="home" expand="true">
<tocitem text="What's new" target="new" expand="true">
<tocitem text="Latest Release Notes" target="release"/>
- <tocitem text="Calculations Dialog" target="calcs.dialog"/>
- <tocitem text="Groovy Features Counter example" target="groovy.featurescounter"/>
- <tocitem text="Custom Colourschemes in Groovy" target="groovy.colours"/>
- <tocitem text="Omit hidden regions in Overview" target="overview"/>
- <tocitem text="Show gaps as grey in overview" target="overviewprefs"/>
- <tocitem text="identifers.org for URL Links" target="linksprefs" />
- <tocitem text="New features in Split Frame View" target="splitframe.mirrorfonts" />
+
</tocitem>
<tocitem text="Editing Alignments" target="edit" />
<p>
To open the PDB Sequence Fetcher, select PDB as the database from
any <a href="seqfetch.html">Sequence Fetcher</a> dialog (opened <em>via</em>
- <strong>"File →Fetch Sequences"</strong>).
+ <strong>"File →Fetch Sequences"</strong>).
</p>
<img src="pdbseqfetcher.png" align="left"
alt="PDB sequence fetcher (introduced in Jalview 2.9)" />
<p>
<strong>Searching the PDB Database</strong>
</p>
+ <p>To search the PDB, begin typing in the text box. If the
+ 'autosearch' checkbox is enabled, then the results of your query
+ will be automatically updated and shown in the search results tab;
+ otherwise, press return to update the results. To access previous
+ searches, press the down-arrow or click the drop down menu icon at
+ the side of the search box. If you just want to paste in a list of
+ IDs, the 'Retrieve IDs' tab provides a batch-retrieval interface.</p>
<p>
- To search the PDB, begin typing in the text box. The results of your
- query are shown in the search results tab, which updates every time
- you type in the search text box. You can sort results according to
- the displayed columns, and select entries with the mouse and
- keyboard. Once you have selected one or more entries, hit the <strong>OK</strong>
- button to retrieve and view them in Jalview.
+ You can sort results according to the displayed columns, and select
+ entries with the mouse and keyboard. Once you have selected one or
+ more entries, hit the <strong>OK</strong> button to retrieve and
+ view them in Jalview.
</p>
<p>
<ul>
1xyz:A</li>
<li><strong>Bulk PDB retrieval</strong><br>Multiple PDB
- IDs can be specified by separating them with a semi-colon.<br />
- e.g. 1xyz;2xyz;3xyz<br />Hitting Return or OK will automatically
- fetch those IDs, like the default Sequence Fetcher interface.</li>
+ IDs can be specified for retrieval via the
+ <strong>Retrieve IDs</strong> tab.</li>
<li><strong>Wild card searching</strong><br>The following
wild cards are supported by the EMBL-EBI PDBe query service:
<p>
<strong>Searching the UniProt Database</strong>
</p>
- <p>
- To search UniProt, simply begin typing in the text box. After a
- short delay (about 1.5 seconds), results will be shown in the table
- below. You can sort results by clicking on the displayed columns,
+ <p>To search UniProt, simply begin typing in the text box. If the
+ 'autosearch' check box is enabled, then after a short delay (about
+ 1.5 seconds), results will be shown in the table below. Results are
+ also updated whenever you press Enter, and you can access previous
+ searches by pressing the 'Down' arrow or clicking the drop-down menu
+ icon at the side of the search box.</p>
+ <p>You can sort results by clicking on the displayed columns,
and select entries with the mouse or keyboard. Once you have
selected one or more entries, hit the <strong>OK</strong> button to
retrieve the sequences.
<li><strong>Bulk UniProt record retrieval</strong><br> To
- retrieve several uniprot accessions at once, first select <strong>UniProt
- ID</strong> from the dropdown menu, then paste in the accession IDs as a
- semi-colon separated list. (e.g. fila_human; mnt_human;
- mnt_mouse).<br />Hitting Return or OK will automatically fetch
- those IDs, like the default Sequence Fetcher interface.</li>
+ retrieve sequences for a list of Uniprot accessions, please enter
+ them via the 'Retrieve IDs' tab.</li>
<li><strong><a name="text-search">Complex queries
with the UniProt query Syntax</a></strong> The text box also allows complex
<td width="60" nowrap>
<div align="center">
<strong><a name="Jalview.2.10.3">2.10.3</a><br />
- <em>14/11/2017</em></strong>
+ <em>17/11/2017</em></strong>
</div>
</td>
<td><div align="left">
<li><!-- JAL-2617 -->Stop codons are excluded in CDS/Protein view from Ensembl locus cross-references</li>
<li><!-- JAL-2685 -->Start/End limits are shown in Pairwise Alignment report</li>
+ <li><!-- JAL-2810 -->Sequence fetcher's Free text 'autosearch' feature can be disabled</li>
+ <li><!-- JAL-2810 -->Retrieve IDs tab added for UniProt and PDB easier retrieval of sequences for lists of IDs</li>
+ <li><!-- JAL-2758 -->Short names for sequences retrieved from Uniprot</li>
+ </ul>
+ <em>Scripting</em>
+ <ul>
+ <li>Groovy interpreter updated to 2.4.12</li>
+ <li>Example groovy script for generating a matrix of percent identity scores for current alignment.</li>
</ul>
- <ul><li>Example groovy script for generating a matrix of percent identity scores for current alignment.</li></ul>
<em>Testing and Deployment</em>
- <ul><li><!-- JAL-2727 -->Test to catch memory leaks in Jalview UI</li></ul>
- </div>
+ <ul>
+ <li><!-- JAL-2727 -->Test to catch memory leaks in Jalview UI</li>
+ </ul>
+ </div>
</td>
<td><div align="left">
<em>General</em>
<li><!-- JAL-2682 -->Race condition when parsing sequence ID strings in parallel</li>
<li><!-- JAL-2608 -->Overview windows are also closed when alignment window is closed</li>
<li><!-- JAL-2548 -->Export of features doesn't always respect group visibility</li>
+ <li><!-- JAL-2831 -->Jumping from column 1 to column 100,000 takes a long time in Cursor mode</li>
</ul>
<em>Desktop</em>
<ul>
<li><!-- JAL-1900,JAL-1625 -->Unable to minimise windows within the Jalview desktop on OSX</li>
<li><!-- JAL-2667 -->Mouse wheel doesn't scroll vertically when in wrapped alignment mode</li>
<li><!-- JAL-2636 -->Scale mark not shown when close to right hand end of alignment</li>
- <li><!-- JAL-2684 -->Pairwise alignment only aligns selected regions of each selected sequence</li>
+ <li><!-- JAL-2684 -->Pairwise alignment of selected regions of each selected sequence do not have correct start/end positions</li>
<li><!-- JAL-2973 -->Alignment ruler height set incorrectly after canceling the Alignment Window's Font dialog</li>
<li><!-- JAL-2036 -->Show cross-references not enabled after restoring project until a new view is created</li>
<li><!-- JAL-2756 -->Warning popup about use of SEQUENCE_ID in URL links appears when only default EMBL-EBI link is configured (since 2.10.2b2)</li>
<li><!-- JAL-2775 -->Overview redraws whole window when box position is adjusted</li>
- <li><!-- JAL-2225 -->Structure viewer doesn't map all chains in a multi-chain structure when viewing alignment involving more than one chain (since 2.10)</li>
+ <li><!-- JAL-2225 -->Structure viewer doesn't map all chains in a multi-chain structure when viewing alignment involving more than one chain (since 2.10)</li>
+ <li><!-- JAL-2811 -->Double residue highlights in cursor mode if new selection moves alignment window</li>
+ <li><!-- JAL-2837,JAL-2840 -->Alignment vanishes when using arrow key in cursor mode to pass hidden column marker</li>
</ul>
<strong><em>Applet</em></strong><br/>
<ul>
<!-- JAL-2546 -->BioJSON export does not preserve non-positional features
</li>
</ul>
+ <strong>Known Java 9 Issues</strong>
+ <ul>
+ <li><!-- JAL-2902 -->Groovy Console very slow to open and is
+ not responsive when entering characters (Webstart, Java 9.01,
+ OSX 10.10)
+ </li>
+ </ul>
+ <strong>New Known Issues</strong>
+ <ul>
+ <li><!-- JAL-2541 -->Delete/Cut selection doesn't relocate sequence features correctly (for many previous versions of Jalview)</li>
+ <li><!-- JAL-2841 -->Cursor mode unexpectedly scrolls when using cursor in wrapped panel other than top</li>
+ <li><!-- JAL-2791 -->Select columns containing feature ignores graduated colour threshold</li>
+ </ul>
</div>
</td>
</tr>
<strong>What's new in Jalview 2.10.3 ?</strong>
</p>
<p>
- Version 2.10.3 is due for release in October 2017. The full list of
+ Version 2.10.3 was released in November 2017. The full list of
bug fixes and new features can be found in the <a
href="releases.html#Jalview.2.10.3"> 2.10.3 Release Notes</a>, but
the highlights are below.
</p>
+ <ul>
+ <li>Faster import and more responsive UI when working with wide alignments and handling hundreds and thousands of sequence features</li>
+ <li>
+ <li>Improved usability with <a href="features/pdbsequencefetcher.html">PDB</a> and
+ <a href="features/uniprotsequencefetcher.html">UniProt</a> Free Text Search
+ dialog, and new tab for retrieval of sequences for lists of IDs.</li>
+ <li>Short names assigned to sequences retrieved from UniProt</li>
+ </ul>
<p>
<strong><a name="experimental">Experimental Features</a></strong>
</p>
label.overview = Overview
label.reset_to_defaults = Reset to defaults
label.oview_calc = Recalculating overview...
+option.enable_disable_autosearch = When ticked, search is performed automatically.
+option.autosearch = Autosearch
+label.retrieve_ids = Retrieve IDs
\ No newline at end of file
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
+ else if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ fastPaint(((int[]) evt.getNewValue())[0]
+ - ((int[]) evt.getOldValue())[0]);
+ }
+ else if (evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ repaint();
+ }
}
}
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
+ else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ fastPaint(((int[]) evt.getNewValue())[1]
+ - ((int[]) evt.getOldValue())[1]);
+ }
+ else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ repaint();
+ }
}
}
// Here we only want to fastpaint on a scroll, with resize using a normal
// paint, so scroll events are identified as changes to the horizontal or
// vertical start value.
- if (evt.getPropertyName().equals(ViewportRanges.STARTRES))
+ if (evt.getPropertyName().equals(ViewportRanges.STARTRES)
+ || evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ)
+ || evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
{
// scroll event, repaint panel
repaint();
{
String eventName = evt.getPropertyName();
+ if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED))
+ {
+ fastPaint = true;
+ repaint();
+ return;
+ }
+ else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ fastPaint = false;
+ repaint();
+ return;
+ }
+
if (!av.getWrapAlignment())
{
int scrollX = 0;
- if (eventName.equals(ViewportRanges.STARTRES))
+ if (eventName.equals(ViewportRanges.STARTRES)
+ || eventName.equals(ViewportRanges.STARTRESANDSEQ))
{
// Make sure we're not trying to draw a panel
// larger than the visible window
+ if (eventName.equals(ViewportRanges.STARTRES))
+ {
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ }
+ else
+ {
+ scrollX = ((int[]) evt.getNewValue())[0]
+ - ((int[]) evt.getOldValue())[0];
+ }
ViewportRanges vpRanges = av.getRanges();
- scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
int range = vpRanges.getEndRes() - vpRanges.getStartRes();
if (scrollX > range)
{
// scroll
fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
+ else if (eventName.equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ fastPaint(scrollX, 0);
+ }
}
}
import jalview.util.MappingUtils;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
-import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.Font;
void setCursorRow()
{
seqCanvas.cursorY = getKeyboardNo1() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void setCursorColumn()
{
seqCanvas.cursorX = getKeyboardNo1() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void setCursorRowAndColumn()
{
seqCanvas.cursorX = getKeyboardNo1() - 1;
seqCanvas.cursorY = getKeyboardNo2() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
}
SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
seqCanvas.cursorX = sequence.findIndex(getKeyboardNo1()) - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void moveCursor(int dx, int dy)
seqCanvas.cursorX = original;
}
}
- scrollToVisible();
+ scrollToVisible(false);
}
- void scrollToVisible()
+ /**
+ * Scroll to make the cursor visible in the viewport.
+ *
+ * @param jump
+ * just jump to the location rather than scrolling
+ */
+ void scrollToVisible(boolean jump)
{
if (seqCanvas.cursorX < 0)
{
}
endEditing();
- if (av.getWrapAlignment())
+
+ boolean repaintNeeded = true;
+ if (jump)
{
- av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
+ // only need to repaint if the viewport did not move, as otherwise it will
+ // get a repaint
+ repaintNeeded = !av.getRanges().setViewportLocation(seqCanvas.cursorX,
+ seqCanvas.cursorY);
}
else
{
- ViewportRanges ranges = av.getRanges();
- HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- while (seqCanvas.cursorY < ranges.getStartSeq())
+ if (av.getWrapAlignment())
{
- ranges.scrollUp(true);
+ av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
}
- while (seqCanvas.cursorY > ranges.getEndSeq())
- {
- ranges.scrollUp(false);
- }
- while (seqCanvas.cursorX < hidden
- .adjustForHiddenColumns(ranges.getStartRes()))
- {
-
- if (!ranges.scrollRight(false))
- {
- break;
- }
- }
- while (seqCanvas.cursorX > hidden
- .adjustForHiddenColumns(ranges.getEndRes()))
+ else
{
- if (!ranges.scrollRight(true))
- {
- break;
- }
+ av.getRanges().scrollToVisible(seqCanvas.cursorX,
+ seqCanvas.cursorY);
}
}
setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
seqCanvas.cursorX, seqCanvas.cursorY);
- seqCanvas.repaint();
+ if (repaintNeeded)
+ {
+ seqCanvas.repaint();
+ }
}
void setSelectionAreaAtCursor(boolean topLeft)
import jalview.util.MessageManager;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
@Override
public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
{
- List<AlignmentAnnotation> aa = new ArrayList<>();
AlignmentAnnotation[] alignmentAnnotation = getAlignmentAnnotation();
if (alignmentAnnotation != null)
{
- for (AlignmentAnnotation a : alignmentAnnotation)
- {
- if (a.getCalcId() == calcId || (a.getCalcId() != null
- && calcId != null && a.getCalcId().equals(calcId)))
- {
- aa.add(a);
- }
- }
+ return AlignmentAnnotation.findAnnotation(
+ Arrays.asList(getAlignmentAnnotation()), calcId);
}
- return aa;
+ return Arrays.asList(new AlignmentAnnotation[] {});
}
@Override
public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label)
{
- ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
- for (AlignmentAnnotation ann : getAlignmentAnnotation())
- {
- if ((calcId == null || (ann.getCalcId() != null
- && ann.getCalcId().equals(calcId)))
- && (seq == null || (ann.sequenceRef != null
- && ann.sequenceRef == seq))
- && (label == null
- || (ann.label != null && ann.label.equals(label))))
- {
- aa.add(ann);
- }
- }
- return aa;
+ return AlignmentAnnotation.findAnnotations(
+ Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
}
@Override
import jalview.analysis.SecStrConsensus.SimpleBP;
import jalview.analysis.WUSSParseException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
{
return graphMin < graphMax;
}
+
+ public static Iterable<AlignmentAnnotation> findAnnotations(
+ Iterable<AlignmentAnnotation> list, SequenceI seq, String calcId,
+ String label)
+ {
+
+ ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
+ for (AlignmentAnnotation ann : list)
+ {
+ if ((calcId == null || (ann.getCalcId() != null
+ && ann.getCalcId().equals(calcId)))
+ && (seq == null || (ann.sequenceRef != null
+ && ann.sequenceRef == seq))
+ && (label == null
+ || (ann.label != null && ann.label.equals(label))))
+ {
+ aa.add(ann);
+ }
+ }
+ return aa;
+ }
+
+ /**
+ * Answer true if any annotation matches the calcId passed in (if not null).
+ *
+ * @param list
+ * annotation to search
+ * @param calcId
+ * @return
+ */
+ public static boolean hasAnnotation(List<AlignmentAnnotation> list,
+ String calcId)
+ {
+
+ if (calcId != null && !"".equals(calcId))
+ {
+ for (AlignmentAnnotation a : list)
+ {
+ if (a.getCalcId() == calcId)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static Iterable<AlignmentAnnotation> findAnnotation(
+ List<AlignmentAnnotation> list, String calcId)
+ {
+
+ List<AlignmentAnnotation> aa = new ArrayList<>();
+ if (calcId == null)
+ {
+ return aa;
+ }
+ for (AlignmentAnnotation a : list)
+ {
+
+ if (a.getCalcId() == calcId || (a.getCalcId() != null
+ && calcId != null && a.getCalcId().equals(calcId)))
+ {
+ aa.add(a);
+ }
+ }
+ return aa;
+ }
}
*/
Vector<AlignmentAnnotation> annotation;
- /**
- * The index of the sequence in a MSA
- */
- int index = -1;
-
private SequenceFeaturesI sequenceFeatureStore;
/*
}
@Override
- public void deleteChars(int i, int j)
+ public void deleteChars(final int i, final int j)
{
int newstart = start, newend = end;
if (i >= sequence.length || i < 0)
boolean createNewDs = false;
// TODO: take a (second look) at the dataset creation validation method for
// the very large sequence case
- int eindex = -1, sindex = -1;
- boolean ecalc = false, scalc = false;
+ int startIndex = findIndex(start) - 1;
+ int endIndex = findIndex(end) - 1;
+ int startDeleteColumn = -1; // for dataset sequence deletions
+ int deleteCount = 0;
+
for (int s = i; s < j; s++)
{
- if (jalview.schemes.ResidueProperties.aaIndex[sequence[s]] != 23)
+ if (Comparison.isGap(sequence[s]))
+ {
+ continue;
+ }
+ deleteCount++;
+ if (startDeleteColumn == -1)
+ {
+ startDeleteColumn = findPosition(s) - start;
+ }
+ if (createNewDs)
+ {
+ newend--;
+ }
+ else
{
- if (createNewDs)
+ if (startIndex == s)
{
- newend--;
+ /*
+ * deleting characters from start of sequence; new start is the
+ * sequence position of the next column (position to the right
+ * if the column position is gapped)
+ */
+ newstart = findPosition(j);
+ break;
}
else
{
- if (!scalc)
+ if (endIndex < j)
{
- sindex = findIndex(start) - 1;
- scalc = true;
- }
- if (sindex == s)
- {
- // delete characters including start of sequence
- newstart = findPosition(j);
- break; // don't need to search for any more residue characters.
+ /*
+ * deleting characters at end of sequence; new end is the sequence
+ * position of the column before the deletion; subtract 1 if this is
+ * gapped since findPosition returns the next sequence position
+ */
+ newend = findPosition(i - 1);
+ if (Comparison.isGap(sequence[i - 1]))
+ {
+ newend--;
+ }
+ break;
}
else
{
- // delete characters after start.
- if (!ecalc)
- {
- eindex = findIndex(end) - 1;
- ecalc = true;
- }
- if (eindex < j)
- {
- // delete characters at end of sequence
- newend = findPosition(i - 1);
- break; // don't need to search for any more residue characters.
- }
- else
- {
- createNewDs = true;
- newend--; // decrease end position by one for the deleted residue
- // and search further
- }
+ createNewDs = true;
+ newend--;
}
}
}
}
- // deletion occured in the middle of the sequence
+
if (createNewDs && this.datasetSequence != null)
{
- // construct a new sequence
+ /*
+ * if deletion occured in the middle of the sequence,
+ * construct a new dataset sequence and delete the residues
+ * that were deleted from the aligned sequence
+ */
Sequence ds = new Sequence(datasetSequence);
+ ds.deleteChars(startDeleteColumn, startDeleteColumn + deleteCount);
+ datasetSequence = ds;
// TODO: remove any non-inheritable properties ?
// TODO: create a sequence mapping (since there is a relation here ?)
- ds.deleteChars(i, j);
- datasetSequence = ds;
}
start = newstart;
end = newend;
}
}
- /**
- * @return The index (zero-based) on this sequence in the MSA. It returns
- * {@code -1} if this information is not available.
- */
- @Override
- public int getIndex()
- {
- return index;
- }
-
- /**
- * Defines the position of this sequence in the MSA. Use the value {@code -1}
- * if this information is undefined.
- *
- * @param The
- * position for this sequence. This value is zero-based (zero for
- * this first sequence)
- */
- @Override
- public void setIndex(int value)
- {
- index = value;
- }
-
@Override
public void setRNA(RNA r)
{
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Override
public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
{
- List<AlignmentAnnotation> aa = new ArrayList<>();
- if (calcId == null)
- {
- return aa;
- }
- for (AlignmentAnnotation a : getAlignmentAnnotation())
- {
- if (calcId.equals(a.getCalcId()))
- {
- aa.add(a);
- }
- }
- return aa;
+ return AlignmentAnnotation.findAnnotation(
+ Arrays.asList(getAlignmentAnnotation()), calcId);
}
@Override
public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label)
{
- ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
- for (AlignmentAnnotation ann : getAlignmentAnnotation())
- {
- if ((calcId == null || (ann.getCalcId() != null
- && ann.getCalcId().equals(calcId)))
- && (seq == null || (ann.sequenceRef != null
- && ann.sequenceRef == seq))
- && (label == null
- || (ann.label != null && ann.label.equals(label))))
- {
- aa.add(ann);
- }
- }
- return aa;
+ return AlignmentAnnotation.findAnnotations(
+ Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
}
/**
*/
public boolean hasAnnotation(String calcId)
{
- if (calcId != null && !"".equals(calcId))
- {
- for (AlignmentAnnotation a : getAlignmentAnnotation())
- {
- if (a.getCalcId() == calcId)
- {
- return true;
- }
- }
- }
- return false;
+ return AlignmentAnnotation
+ .hasAnnotation(Arrays.asList(getAlignmentAnnotation()), calcId);
}
/**
public int findIndex(int pos);
/**
- * Returns the sequence position for an alignment position.
+ * Returns the sequence position for an alignment (column) position. If at a
+ * gap, returns the position of the next residue to the right. If beyond the
+ * end of the sequence, returns 1 more than the last residue position.
*
* @param i
* column index in alignment (from 0..<length)
*
- * @return TODO: JAL-2562 - residue number for residue (left of and) nearest
- * ith column
+ * @return
*/
public int findPosition(int i);
public void transferAnnotation(SequenceI entry, Mapping mp);
/**
- * @param index
- * The sequence index in the MSA
- */
- public void setIndex(int index);
-
- /**
- * @return The index of the sequence in the alignment
- */
- public int getIndex();
-
- /**
* @return The RNA of the sequence in the alignment
*/
return "EnsemblGenomes";
}
- private String Wrong[];
@Override
public String getTestQuery()
{
- return "DDB_G0283883";
+ /*
+ * Salmonella gene, Uniprot Q8Z9G6, EMBLCDS CAD01290
+ */
+ return "CAD01290";
}
@Override
* @return
*/
public String getCacheKey();
+
+ /**
+ *
+ * @return user preference name for configuring this FTS search's autosearch
+ * checkbox
+ */
+ public String getAutosearchPreference();
}
import javax.swing.ImageIcon;
import javax.swing.JButton;
+import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
protected JInternalFrame mainFrame = new JInternalFrame(
getFTSFrameTitle());
+ protected JTabbedPane tabs = new JTabbedPane();
protected IProgressIndicator progressIndicator;
protected JComboBox<FTSDataColumnI> cmb_searchTarget = new JComboBox<FTSDataColumnI>();
protected JButton btn_cancel = new JButton();
+ protected JCheckBox btn_autosearch = new JCheckBox();
+
protected JvCacheableInputBox<String> txt_search;
protected SequenceFetcher seqFetcher;
public GFTSPanel()
{
+ this(null);
+ }
+
+ public GFTSPanel(SequenceFetcher fetcher)
+ {
try
{
+ if (fetcher == null)
+ {
+ tabs = null;
+ }
jbInit();
+ if (fetcher != null)
+ {
+ tabs.addTab(MessageManager.getString("label.retrieve_ids"),
+ fetcher);
+ fetcher.setDatabaseChooserVisible(false);
+ fetcher.embedWithFTSPanel(this);
+ }
mainFrame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
+ final JPanel ftsPanel = this;
mainFrame.addFocusListener(new FocusAdapter()
{
@Override
public void focusGained(FocusEvent e)
{
- txt_search.requestFocusInWindow();
+ // TODO: make selected tab gain focus in correct widget
+ if (tabs != null
+ && tabs.getSelectedComponent() == ftsPanel)
+ {
+ txt_search.requestFocusInWindow();
+ }
}
});
mainFrame.invalidate();
}
});
+ btn_autosearch.setText(MessageManager.getString("option.autosearch"));
+ btn_autosearch.setToolTipText(
+ MessageManager.getString("option.enable_disable_autosearch"));
+ btn_autosearch.setSelected(
+ jalview.bin.Cache.getDefault(getAutosearchPreference(), true));
+ btn_autosearch.addActionListener(new java.awt.event.ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ jalview.bin.Cache.setProperty(getAutosearchPreference(),
+ Boolean.toString(btn_autosearch.isSelected()));
+ }
+ });
btn_back.setFont(new java.awt.Font("Verdana", 0, 12));
btn_back.setText(MessageManager.getString("action.back"));
btn_back.addActionListener(new java.awt.event.ActionListener()
if (primaryKeyName.equalsIgnoreCase(getCmbSearchTarget()
.getSelectedItem().toString()))
{
+ // TODO: nicer to show the list in the result set before
+ // viewing in Jalview perhaps ?
transferToSequenceFetcher(getTypedText());
}
+ else
+ {
+ performSearchAction();
+ }
}
}
});
@Override
public void actionPerformed(ActionEvent e)
{
- String typed = getTypedText();
- if (!typed.equalsIgnoreCase(lastSearchTerm))
+ if (btn_autosearch.isSelected()
+ || txt_search.wasEnterPressed())
{
- searchAction(true);
- paginatorCart.clear();
- lastSearchTerm = typed;
+ performSearchAction();
}
}
}, false);
}
});
+ txt_search.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ performSearchAction();
+ }
+ });
final String searchTabTitle = MessageManager
.getString("label.search_result");
final String configureCols = MessageManager
pnl_results.add(tabbedPane);
pnl_inputs.add(cmb_searchTarget);
pnl_inputs.add(txt_search);
+ pnl_inputs.add(btn_autosearch);
pnl_inputs.add(lbl_loading);
pnl_inputs.add(lbl_warning);
pnl_inputs.add(lbl_blank);
this.add(pnl_results, java.awt.BorderLayout.CENTER);
this.add(pnl_actions, java.awt.BorderLayout.SOUTH);
mainFrame.setVisible(true);
- mainFrame.setContentPane(this);
+ if (tabs != null)
+ {
+ tabs.setOpaque(true);
+ tabs.insertTab("Free Text Search", null, this, "", 0);
+ mainFrame.setContentPane(tabs);
+ tabs.setVisible(true);
+ }
+ else
+ {
+ mainFrame.setContentPane(this);
+ }
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.addInternalFrameListener(
new javax.swing.event.InternalFrameAdapter()
closeAction();
}
});
- mainFrame.setVisible(true);
- mainFrame.setContentPane(this);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Integer x = getTempUserPrefs().get("FTSPanel.x");
Integer y = getTempUserPrefs().get("FTSPanel.y");
}
+ void performSearchAction()
+ {
+ String typed = getTypedText();
+ if (typed != null && typed.length() > 0
+ && !typed.equalsIgnoreCase(lastSearchTerm))
+ {
+ searchAction(true);
+ paginatorCart.clear();
+ lastSearchTerm = typed;
+ }
+ }
+
public boolean wantedFieldsUpdated()
{
if (previousWantedFields == null)
}
}
- protected void btn_back_ActionPerformed()
+ public void btn_back_ActionPerformed()
{
closeAction();
new SequenceFetcher(progressIndicator);
btn_cancel.setEnabled(false);
}
- protected void btn_cancel_ActionPerformed()
+ public void btn_cancel_ActionPerformed()
{
closeAction();
}
private static final String PDB_FTS_CACHE_KEY = "CACHE.PDB_FTS";
+ private static final String PDB_AUTOSEARCH = "FTS.PDB.AUTOSEARCH";
+
public PDBFTSPanel(SequenceFetcher fetcher)
{
- super();
+ super(fetcher);
pageLimit = PDBFTSRestClient.getInstance().getDefaultResponsePageSize();
this.seqFetcher = fetcher;
this.progressIndicator = (fetcher == null) ? null
return PDB_FTS_CACHE_KEY;
}
-}
+ @Override
+ public String getAutosearchPreference()
+ {
+ return PDB_AUTOSEARCH;
+ }
+}
\ No newline at end of file
private static final String UNIPROT_FTS_CACHE_KEY = "CACHE.UNIPROT_FTS";
+ private static final String UNIPROT_AUTOSEARCH = "FTS.UNIPROT.AUTOSEARCH";
+
public UniprotFTSPanel(SequenceFetcher fetcher)
{
- super();
+ super(fetcher);
pageLimit = UniProtFTSRestClient.getInstance()
.getDefaultResponsePageSize();
this.seqFetcher = fetcher;
{
return UNIPROT_FTS_CACHE_KEY;
}
+
+ @Override
+ public String getAutosearchPreference()
+ {
+ return UNIPROT_AUTOSEARCH;
+ }
}
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
+ else if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ fastPaint(((int[]) evt.getNewValue())[0]
+ - ((int[]) evt.getOldValue())[0]);
+ }
+ else if (evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ repaint();
+ }
}
}
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
+ else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ fastPaint(((int[]) evt.getNewValue())[1]
+ - ((int[]) evt.getOldValue())[1]);
+ }
+ else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ repaint();
+ }
}
}
// Here we only want to fastpaint on a scroll, with resize using a normal
// paint, so scroll events are identified as changes to the horizontal or
// vertical start value.
- if (evt.getPropertyName().equals(ViewportRanges.STARTRES))
+ if (evt.getPropertyName().equals(ViewportRanges.STARTRES)
+ || evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ)
+ || evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
{
// scroll event, repaint panel
repaint();
int transX = 0;
int transY = 0;
- gg.copyArea(horizontal * charWidth, vertical * charHeight,
- img.getWidth(), img.getHeight(), -horizontal * charWidth,
- -vertical * charHeight);
+ gg.copyArea(horizontal * charWidth, vertical * charHeight,
+ img.getWidth(), img.getHeight(), -horizontal * charWidth,
+ -vertical * charHeight);
- if (horizontal > 0) // scrollbar pulled right, image to the left
- {
- transX = (endRes - startRes - horizontal) * charWidth;
- startRes = endRes - horizontal;
- }
- else if (horizontal < 0)
- {
- endRes = startRes - horizontal;
- }
- else if (vertical > 0) // scroll down
- {
- startSeq = endSeq - vertical;
-
- if (startSeq < ranges.getStartSeq())
- { // ie scrolling too fast, more than a page at a time
- startSeq = ranges.getStartSeq();
+ if (horizontal > 0) // scrollbar pulled right, image to the left
+ {
+ transX = (endRes - startRes - horizontal) * charWidth;
+ startRes = endRes - horizontal;
}
- else
+ else if (horizontal < 0)
{
- transY = img.getHeight() - ((vertical + 1) * charHeight);
+ endRes = startRes - horizontal;
}
- }
- else if (vertical < 0)
- {
- endSeq = startSeq - vertical;
- if (endSeq > ranges.getEndSeq())
+ if (vertical > 0) // scroll down
{
- endSeq = ranges.getEndSeq();
+ startSeq = endSeq - vertical;
+
+ if (startSeq < ranges.getStartSeq())
+ { // ie scrolling too fast, more than a page at a time
+ startSeq = ranges.getStartSeq();
+ }
+ else
+ {
+ transY = img.getHeight() - ((vertical + 1) * charHeight);
+ }
}
- }
+ else if (vertical < 0)
+ {
+ endSeq = startSeq - vertical;
- gg.translate(transX, transY);
- drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
- gg.translate(-transX, -transY);
+ if (endSeq > ranges.getEndSeq())
+ {
+ endSeq = ranges.getEndSeq();
+ }
+ }
- repaint();
+ gg.translate(transX, transY);
+ drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
+ gg.translate(-transX, -transY);
+
+ repaint();
} finally
{
fastpainting = false;
// lcimg is a local *copy* of img which we'll draw selectImage on top of
BufferedImage lcimg = buildLocalImage(selectImage);
g.drawImage(lcimg, 0, 0, this);
+
+ }
+
+ if (av.cursorMode)
+ {
+ drawCursor(g, ranges.getStartRes(), ranges.getEndRes(),
+ ranges.getStartSeq(), ranges.getEndSeq());
}
}
AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
g2d.drawImage(selectImage, 0, 0, this);
}
+
g2d.dispose();
return lcimg;
int canvasWidth,
int canvasHeight, int startRes)
{
- int charHeight = av.getCharHeight();
- int charWidth = av.getCharWidth();
-
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
// height gap above each panel
int hgap = charHeight;
if (av.getScaleAboveWrapped())
}
}
}
-
- if (av.cursorMode && cursorY == i && cursorX >= startRes
- && cursorX <= endRes)
- {
- seqRdr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth,
- offset + ((i - startSeq) * charHeight));
- }
}
if (av.getSelectionGroup() != null
return selectionImage;
}
+ /**
+ * Draw the cursor as a separate image and overlay
+ *
+ * @param startRes
+ * start residue of area to draw cursor in
+ * @param endRes
+ * end residue of area to draw cursor in
+ * @param startSeq
+ * start sequence of area to draw cursor in
+ * @param endSeq
+ * end sequence of are to draw cursor in
+ * @return a transparent image of the same size as the sequence canvas, with
+ * the cursor drawn on it, if any
+ */
+ private void drawCursor(Graphics g, int startRes, int endRes,
+ int startSeq,
+ int endSeq)
+ {
+ // convert the cursorY into a position on the visible alignment
+ int cursor_ypos = cursorY;
+
+ // don't do work unless we have to
+ if (cursor_ypos >= startSeq && cursor_ypos <= endSeq)
+ {
+ int yoffset = 0;
+ int xoffset = 0;
+ int startx = startRes;
+ int endx = endRes;
+
+ // convert the cursorX into a position on the visible alignment
+ int cursor_xpos = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(cursorX);
+
+ if (av.getAlignment().getHiddenColumns().isVisible(cursorX))
+ {
+
+ if (av.getWrapAlignment())
+ {
+ // work out the correct offsets for the cursor
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+ int canvasWidth = getWidth();
+ int canvasHeight = getHeight();
+
+ // height gap above each panel
+ int hgap = charHeight;
+ if (av.getScaleAboveWrapped())
+ {
+ hgap += charHeight;
+ }
+
+ int cWidth = (canvasWidth - labelWidthEast - labelWidthWest)
+ / charWidth;
+ int cHeight = av.getAlignment().getHeight() * charHeight;
+
+ endx = startx + cWidth - 1;
+ int ypos = hgap; // vertical offset
+
+ // iterate down the wrapped panels
+ while ((ypos <= canvasHeight) && (endx < cursor_xpos))
+ {
+ // update vertical offset
+ ypos += cHeight + getAnnotationHeight() + hgap;
+
+ // update horizontal offset
+ startx += cWidth;
+ endx = startx + cWidth - 1;
+ }
+ yoffset = ypos;
+ xoffset = labelWidthWest;
+ }
+
+ // now check if cursor is within range for x values
+ if (cursor_xpos >= startx && cursor_xpos <= endx)
+ {
+ // get the character the cursor is drawn at
+ SequenceI seq = av.getAlignment().getSequenceAt(cursorY);
+ char s = seq.getCharAt(cursorX);
+
+ seqRdr.drawCursor(g, s,
+ xoffset + (cursor_xpos - startx) * av.getCharWidth(),
+ yoffset + (cursor_ypos - startSeq) * av.getCharHeight());
+ }
+ }
+ }
+ }
+
+
/*
* Set up graphics for selection group
*/
private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
int startRes, int endRes, int startSeq, int endSeq, int offset)
{
- int charWidth = av.getCharWidth();
-
+ int charWidth = av.getCharWidth();
+
if (!av.hasHiddenColumns())
{
drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
int startRes, int endRes, int startSeq, int endSeq,
int verticalOffset)
{
- int charHeight = av.getCharHeight();
- int charWidth = av.getCharWidth();
-
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
int visWidth = (endRes - startRes + 1) * charWidth;
int oldY = -1;
boolean inGroup = false;
int top = -1;
int bottom = -1;
-
- int sx = -1;
int sy = -1;
- int xwidth = -1;
- for (i = startSeq; i <= endSeq; i++)
- {
- // position of start residue of group relative to startRes, in pixels
- sx = (group.getStartRes() - startRes) * charWidth;
+ List<SequenceI> seqs = group.getSequences(null);
- // width of group in pixels
- xwidth = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth)
- - 1;
+ // position of start residue of group relative to startRes, in pixels
+ int sx = (group.getStartRes() - startRes) * charWidth;
- sy = verticalOffset + (i - startSeq) * charHeight;
+ // width of group in pixels
+ int xwidth = (((group.getEndRes() + 1) - group.getStartRes())
+ * charWidth) - 1;
- if (sx + xwidth < 0 || sx > visWidth)
- {
- continue;
- }
-
- if ((sx <= (endRes - startRes) * charWidth)
- && group.getSequences(null)
- .contains(av.getAlignment().getSequenceAt(i)))
+ if (!(sx + xwidth < 0 || sx > visWidth))
+ {
+ for (i = startSeq; i <= endSeq; i++)
{
- if ((bottom == -1) && !group.getSequences(null)
- .contains(av.getAlignment().getSequenceAt(i + 1)))
- {
- bottom = sy + charHeight;
- }
+ sy = verticalOffset + (i - startSeq) * charHeight;
- if (!inGroup)
- {
- if (((top == -1) && (i == 0)) || !group.getSequences(null)
- .contains(av.getAlignment().getSequenceAt(i - 1)))
- {
- top = sy;
- }
-
- oldY = sy;
- inGroup = true;
- }
- }
- else
- {
- if (inGroup)
+ if ((sx <= (endRes - startRes) * charWidth)
+ && seqs.contains(av.getAlignment().getSequenceAt(i)))
{
- // if start position is visible, draw vertical line to left of
- // group
- if (sx >= 0 && sx < visWidth)
- {
- g.drawLine(sx, oldY, sx, sy);
- }
-
- // if end position is visible, draw vertical line to right of
- // group
- if (sx + xwidth < visWidth)
+ if ((bottom == -1)
+ && !seqs.contains(av.getAlignment().getSequenceAt(i + 1)))
{
- g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
+ bottom = sy + charHeight;
}
- if (sx < 0)
- {
- xwidth += sx;
- sx = 0;
- }
-
- // don't let width extend beyond current block, or group extent
- // fixes JAL-2672
- if (sx + xwidth >= (endRes - startRes + 1) * charWidth)
- {
- xwidth = (endRes - startRes + 1) * charWidth - sx;
- }
-
- // draw horizontal line at top of group
- if (top != -1)
+ if (!inGroup)
{
- g.drawLine(sx, top, sx + xwidth, top);
- top = -1;
- }
+ if (((top == -1) && (i == 0)) || !seqs
+ .contains(av.getAlignment().getSequenceAt(i - 1)))
+ {
+ top = sy;
+ }
- // draw horizontal line at bottom of group
- if (bottom != -1)
- {
- g.drawLine(sx, bottom, sx + xwidth, bottom);
- bottom = -1;
+ oldY = sy;
+ inGroup = true;
}
+ }
+ else if (inGroup)
+ {
+ drawVerticals(g, sx, xwidth, visWidth, oldY, sy);
+ drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
+ // reset top and bottom
+ top = -1;
+ bottom = -1;
inGroup = false;
}
}
- }
-
- if (inGroup)
- {
- sy = verticalOffset + ((i - startSeq) * charHeight);
- if (sx >= 0 && sx < visWidth)
+ if (inGroup)
{
- g.drawLine(sx, oldY, sx, sy);
+ sy = verticalOffset + ((i - startSeq) * charHeight);
+ drawVerticals(g, sx, xwidth, visWidth, oldY, sy);
+ drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
}
+ }
+ }
- if (sx + xwidth < visWidth)
- {
- g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
- }
+ /**
+ * Draw horizontal selection group boundaries at top and bottom positions
+ *
+ * @param g
+ * graphics object to draw on
+ * @param sx
+ * start x position
+ * @param xwidth
+ * width of gap
+ * @param visWidth
+ * visWidth maximum available width
+ * @param top
+ * position to draw top of group at
+ * @param bottom
+ * position to draw bottom of group at
+ */
+ private void drawHorizontals(Graphics2D g, int sx, int xwidth,
+ int visWidth, int top, int bottom)
+ {
+ int width = xwidth;
+ int startx = sx;
+ if (startx < 0)
+ {
+ width += startx;
+ startx = 0;
+ }
- if (sx < 0)
- {
- xwidth += sx;
- sx = 0;
- }
+ // don't let width extend beyond current block, or group extent
+ // fixes JAL-2672
+ if (startx + width >= visWidth)
+ {
+ width = visWidth - startx;
+ }
- if (sx + xwidth > visWidth)
- {
- xwidth = visWidth;
- }
- else if (sx + xwidth >= (endRes - startRes + 1) * charWidth)
- {
- xwidth = (endRes - startRes + 1) * charWidth;
- }
+ if (top != -1)
+ {
+ g.drawLine(startx, top, startx + width, top);
+ }
- if (top != -1)
- {
- g.drawLine(sx, top, sx + xwidth, top);
- top = -1;
- }
+ if (bottom != -1)
+ {
+ g.drawLine(startx, bottom - 1, startx + width, bottom - 1);
+ }
+ }
- if (bottom != -1)
- {
- g.drawLine(sx, bottom - 1, sx + xwidth, bottom - 1);
- bottom = -1;
- }
+ /**
+ * Draw vertical lines at sx and sx+xwidth providing they lie within
+ * [0,visWidth)
+ *
+ * @param g
+ * graphics object to draw on
+ * @param sx
+ * start x position
+ * @param xwidth
+ * width of gap
+ * @param visWidth
+ * visWidth maximum available width
+ * @param oldY
+ * top y value
+ * @param sy
+ * bottom y value
+ */
+ private void drawVerticals(Graphics2D g, int sx, int xwidth, int visWidth,
+ int oldY, int sy)
+ {
+ // if start position is visible, draw vertical line to left of
+ // group
+ if (sx >= 0 && sx < visWidth)
+ {
+ g.drawLine(sx, oldY, sx, sy);
+ }
- inGroup = false;
+ // if end position is visible, draw vertical line to right of
+ // group
+ if (sx + xwidth < visWidth)
+ {
+ g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
}
}
repaint();
return;
}
+ else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ fastPaint = false;
+ repaint();
+ return;
+ }
int scrollX = 0;
- if (eventName.equals(ViewportRanges.STARTRES))
+ if (eventName.equals(ViewportRanges.STARTRES)
+ || eventName.equals(ViewportRanges.STARTRESANDSEQ))
{
// Make sure we're not trying to draw a panel
// larger than the visible window
+ if (eventName.equals(ViewportRanges.STARTRES))
+ {
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ }
+ else
+ {
+ scrollX = ((int[]) evt.getNewValue())[0]
+ - ((int[]) evt.getOldValue())[0];
+ }
ViewportRanges vpRanges = av.getRanges();
- scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
- int range = vpRanges.getViewportWidth();
+
+ int range = vpRanges.getEndRes() - vpRanges.getStartRes();
if (scrollX > range)
{
scrollX = range;
{
scrollX = -range;
}
- }
-
- // Both scrolling and resizing change viewport ranges: scrolling changes
- // both start and end points, but resize only changes end values.
- // Here we only want to fastpaint on a scroll, with resize using a normal
- // paint, so scroll events are identified as changes to the horizontal or
- // vertical start value.
- // scroll - startres and endres both change
- if (eventName.equals(ViewportRanges.STARTRES))
- {
- if (av.getWrapAlignment())
+ // Both scrolling and resizing change viewport ranges: scrolling changes
+ // both start and end points, but resize only changes end values.
+ // Here we only want to fastpaint on a scroll, with resize using a normal
+ // paint, so scroll events are identified as changes to the horizontal or
+ // vertical start value.
+ if (eventName.equals(ViewportRanges.STARTRES))
{
- fastPaintWrapped(scrollX);
+ if (av.getWrapAlignment())
+ {
+ fastPaintWrapped(scrollX);
+ }
+ else
+ {
+ fastPaint(scrollX, 0);
+ }
}
- else
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
{
- fastPaint(scrollX, 0);
+ // scroll
+ fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+ }
+ else if (eventName.equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ if (av.getWrapAlignment())
+ {
+ fastPaintWrapped(scrollX);
+ }
+ else
+ {
+ fastPaint(scrollX, 0);
+ }
+ // bizarrely, we only need to scroll on the x value here as fastpaint
+ // copies the full height of the image anyway. Passing in the y value
+ // causes nasty repaint artefacts, which only disappear on a full
+ // repaint.
}
- }
- else if (eventName.equals(ViewportRanges.STARTSEQ))
- {
- // scroll
- fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
}
{
ViewportRanges ranges = av.getRanges();
- if (Math.abs(scrollX) > ranges.getViewportWidth())
+ // if (Math.abs(scrollX) > ranges.getViewportWidth())
+ // JAL-2836, 2836 temporarily removed wrapped fastpaint for release 2.10.3
+ if (true)
{
/*
* shift of more than one view width is
void setCursorRow()
{
seqCanvas.cursorY = getKeyboardNo1() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void setCursorColumn()
{
seqCanvas.cursorX = getKeyboardNo1() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void setCursorRowAndColumn()
{
seqCanvas.cursorX = getKeyboardNo1() - 1;
seqCanvas.cursorY = getKeyboardNo2() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
}
SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
seqCanvas.cursorX = sequence.findIndex(getKeyboardNo1()) - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void moveCursor(int dx, int dy)
}
}
- scrollToVisible();
+ scrollToVisible(false);
}
- void scrollToVisible()
+ /**
+ * Scroll to make the cursor visible in the viewport.
+ *
+ * @param jump
+ * just jump to the location rather than scrolling
+ */
+ void scrollToVisible(boolean jump)
{
if (seqCanvas.cursorX < 0)
{
}
endEditing();
- if (av.getWrapAlignment())
+
+ boolean repaintNeeded = true;
+ if (jump)
{
- av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
+ // only need to repaint if the viewport did not move, as otherwise it will
+ // get a repaint
+ repaintNeeded = !av.getRanges().setViewportLocation(seqCanvas.cursorX,
+ seqCanvas.cursorY);
}
else
{
- av.getRanges().scrollToVisible(seqCanvas.cursorX, seqCanvas.cursorY);
+ if (av.getWrapAlignment())
+ {
+ // scrollToWrappedVisible expects x-value to have hidden cols subtracted
+ int x = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(seqCanvas.cursorX);
+ av.getRanges().scrollToWrappedVisible(x);
+ }
+ else
+ {
+ av.getRanges().scrollToVisible(seqCanvas.cursorX,
+ seqCanvas.cursorY);
+ }
}
- setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
+
+ if (av.getAlignment().getHiddenColumns().isVisible(seqCanvas.cursorX))
+ {
+ setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
seqCanvas.cursorX, seqCanvas.cursorY);
+ }
- seqCanvas.repaint();
+ if (repaintNeeded)
+ {
+ seqCanvas.repaint();
+ }
}
+
void setSelectionAreaAtCursor(boolean topLeft)
{
SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
import jalview.datamodel.DBRefEntry;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
+import jalview.fts.core.GFTSPanel;
import jalview.fts.service.pdb.PDBFTSPanel;
import jalview.fts.service.uniprot.UniprotFTSPanel;
import jalview.io.FileFormatI;
JButton close = new JButton();
+ JButton back = new JButton();
+
JPanel jPanel1 = new JPanel();
JTextArea textArea = new JTextArea();
.getString("label.additional_sequence_fetcher"));
}
+ GFTSPanel parentFTSframe = null;
+ /**
+ * change the buttons so they fit with the FTS panel.
+ */
+ public void embedWithFTSPanel(GFTSPanel toClose)
+ {
+ back.setVisible(true);
+ parentFTSframe = toClose;
+ }
private void jbInit() throws Exception
{
this.setLayout(borderLayout2);
example_actionPerformed();
}
});
- close.setText(MessageManager.getString("action.close"));
+ close.setText(MessageManager.getString("action.cancel"));
close.addActionListener(new ActionListener()
{
@Override
close_actionPerformed(e);
}
});
+ back.setText(MessageManager.getString("action.back"));
+ back.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ parentFTSframe.btn_back_ActionPerformed();
+ }
+ });
+ // back not visible unless embedded
+ back.setVisible(false);
textArea.setFont(JvSwingUtils.getLabelFont());
textArea.setLineWrap(true);
textArea.addKeyListener(new KeyAdapter()
});
jPanel3.setLayout(borderLayout1);
borderLayout1.setVgap(5);
- jPanel1.add(ok);
+ jPanel1.add(back);
jPanel1.add(example);
jPanel1.add(clear);
+ jPanel1.add(ok);
jPanel1.add(close);
jPanel2.setLayout(borderLayout3);
databaseButt = /*database.getDatabaseSelectorButton();
try
{
frame.setClosed(true);
+ if (parentFTSframe!=null)
+ {
+ parentFTSframe.btn_cancel_ActionPerformed();
+ }
} catch (Exception ex)
{
}
textArea.setEnabled(false);
ok.setEnabled(false);
close.setEnabled(false);
-
+ back.setEnabled(false);
Thread worker = new Thread(this);
worker.start();
}
textArea.setEnabled(true);
ok.setEnabled(true);
close.setEnabled(true);
+ back.setEnabled(parentFTSframe != null);
}
@Override
{
frame.setVisible(false);
}
+
+ public void setDatabaseChooserVisible(boolean b)
+ {
+ databaseButt.setVisible(b);
+ }
}
}
}
- public void drawCursor(SequenceI seq, int res, int x1, int y1)
+ /**
+ * Draw a sequence canvas cursor
+ *
+ * @param g
+ * graphics context to draw on
+ * @param s
+ * character to draw at cursor
+ * @param x1
+ * x position of cursor in graphics context
+ * @param y1
+ * y position of cursor in graphics context
+ */
+ public void drawCursor(Graphics g, char s, int x1, int y1)
{
int pady = av.getCharHeight() / 5;
int charOffset = 0;
- graphics.setColor(Color.black);
- graphics.fillRect(x1, y1, av.getCharWidth(), av.getCharHeight());
+ g.setColor(Color.black);
+ g.fillRect(x1, y1, av.getCharWidth(), av.getCharHeight());
if (av.isValidCharWidth())
{
- graphics.setColor(Color.white);
-
- char s = seq.getCharAt(res);
-
+ g.setColor(Color.white);
charOffset = (av.getCharWidth() - fm.charWidth(s)) / 2;
- graphics.drawString(String.valueOf(s), charOffset + x1,
+ g.drawString(String.valueOf(s), charOffset + x1,
(y1 + av.getCharHeight()) - pady);
}
}
parseCalled = true;
parse();
- // sets the index of each sequence in the alignment
- for (int i = 0, c = seqs.size(); i < c; i++)
- {
- seqs.get(i).setIndex(i);
- }
}
/**
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
private JMenuItem menuItemClearCache = new JMenuItem();
+ volatile boolean enterWasPressed = false;
+
+ /**
+ * @return flag indicating if the most recent keypress was enter
+ */
+ public boolean wasEnterPressed()
+ {
+ return enterWasPressed;
+ }
+
public JvCacheableInputBox(String newCacheKey)
{
super();
this.cacheKey = newCacheKey;
setEditable(true);
+ addKeyListener(new KeyListener()
+ {
+
+ @Override
+ public void keyTyped(KeyEvent e)
+ {
+ enterWasPressed = false;
+ if (e.getKeyCode() == KeyEvent.VK_ENTER)
+ {
+ enterWasPressed = true;
+ }
+ // let event bubble up
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e)
+ {
+ // TODO Auto-generated method stub
+
+ }
+ });
setPrototypeDisplayValue(
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
appCache = AppCache.getInstance();
}
}
- // update viewport
- ranges.setStartRes(xAsRes);
- ranges.setStartSeq(yAsSeq);
+ ranges.setStartResAndSeq(xAsRes, yAsSeq);
}
@Override
}
// update viewport
- ranges.setStartRes(visXAsRes);
- ranges.setStartSeq(visYAsSeq);
+ ranges.setStartResAndSeq(visXAsRes, visYAsSeq);
}
/**
import jalview.datamodel.HiddenColumns;
/**
- * Slightly less embryonic class which: Supplies and updates viewport properties
- * relating to position such as: start and end residues and sequences; ideally
- * will serve hidden columns/rows too. Intention also to support calculations
- * for positioning, scrolling etc. such as finding the middle of the viewport,
- * checking for scrolls off screen
+ * Supplies and updates viewport properties relating to position such as: start
+ * and end residues and sequences; ideally will serve hidden columns/rows too.
+ * Intention also to support calculations for positioning, scrolling etc. such
+ * as finding the middle of the viewport, checking for scrolls off screen
*/
public class ViewportRanges extends ViewportProperties
{
public static final String ENDSEQ = "endseq";
+ public static final String STARTRESANDSEQ = "startresandseq";
+
+ public static final String MOVE_VIEWPORT = "move_viewport";
+
private boolean wrappedMode = false;
// start residue of viewport
*/
public void setStartEndRes(int start, int end)
{
+ int[] oldvalues = updateStartEndRes(start, end);
+ int oldstartres = oldvalues[0];
+ int oldendres = oldvalues[1];
+
+ changeSupport.firePropertyChange(STARTRES, oldstartres, startRes);
+ if (oldstartres == startRes)
+ {
+ // event won't be fired if start positions are same
+ // fire an event for the end positions in case they changed
+ changeSupport.firePropertyChange(ENDRES, oldendres, endRes);
+ }
+ }
+
+ /**
+ * Update start and end residue values, adjusting for width constraints if
+ * necessary
+ *
+ * @param start
+ * start residue
+ * @param end
+ * end residue
+ * @return array containing old start and end residue values
+ */
+ private int[] updateStartEndRes(int start, int end)
+ {
int oldstartres = this.startRes;
/*
{
endRes = end;
}
-
- changeSupport.firePropertyChange(STARTRES, oldstartres, startRes);
- if (oldstartres == startRes)
- {
- // event won't be fired if start positions are same
- // fire an event for the end positions in case they changed
- changeSupport.firePropertyChange(ENDRES, oldendres, endRes);
- }
+ return new int[] { oldstartres, oldendres };
}
/**
*/
public void setStartEndSeq(int start, int end)
{
+ int[] oldvalues = updateStartEndSeq(start, end);
+ int oldstartseq = oldvalues[0];
+ int oldendseq = oldvalues[1];
+
+ changeSupport.firePropertyChange(STARTSEQ, oldstartseq, startSeq);
+ if (oldstartseq == startSeq)
+ {
+ // event won't be fired if start positions are the same
+ // fire in case the end positions changed
+ changeSupport.firePropertyChange(ENDSEQ, oldendseq, endSeq);
+ }
+ }
+
+ /**
+ * Update start and end sequence values, adjusting for height constraints if
+ * necessary
+ *
+ * @param start
+ * start sequence
+ * @param end
+ * end sequence
+ * @return array containing old start and end sequence values
+ */
+ private int[] updateStartEndSeq(int start, int end)
+ {
int oldstartseq = this.startSeq;
int visibleHeight = getVisibleAlignmentHeight();
if (start > visibleHeight - 1)
{
endSeq = end;
}
-
- changeSupport.firePropertyChange(STARTSEQ, oldstartseq, startSeq);
- if (oldstartseq == startSeq)
- {
- // event won't be fired if start positions are the same
- // fire in case the end positions changed
- changeSupport.firePropertyChange(ENDSEQ, oldendseq, endSeq);
- }
+ return new int[] { oldstartseq, oldendseq };
}
/**
}
/**
+ * Set start residue and start sequence together (fires single event). The
+ * event supplies a pair of old values and a pair of new values: [old start
+ * residue, old start sequence] and [new start residue, new start sequence]
+ *
+ * @param res
+ * the start residue
+ * @param seq
+ * the start sequence
+ */
+ public void setStartResAndSeq(int res, int seq)
+ {
+ int width = getViewportWidth();
+ int[] oldresvalues = updateStartEndRes(res, res + width - 1);
+
+ int startseq = seq;
+ int height = getViewportHeight();
+ if (startseq + height - 1 > getVisibleAlignmentHeight() - 1)
+ {
+ startseq = getVisibleAlignmentHeight() - height;
+ }
+ int[] oldseqvalues = updateStartEndSeq(startseq, startseq + height - 1);
+
+ int[] old = new int[] { oldresvalues[0], oldseqvalues[0] };
+ int[] newresseq = new int[] { startRes, startSeq };
+ changeSupport.firePropertyChange(STARTRESANDSEQ, old, newresseq);
+ }
+
+ /**
* Get start residue of viewport
*/
public int getStartRes()
* the startRes changed, else false.
*
* @param res
- * residue position to scroll to
+ * residue position to scroll to NB visible position not absolute
+ * alignment position
* @return
*/
public boolean scrollToWrappedVisible(int res)
{
- int oldStartRes = startRes;
- int width = getViewportWidth();
-
- if (res >= oldStartRes && res < oldStartRes + width)
+ int newStartRes = calcWrappedStartResidue(res);
+ if (newStartRes == startRes)
{
return false;
}
+ setStartRes(newStartRes);
+
+ return true;
+ }
+
+ /**
+ * Calculate wrapped start residue from visible start residue
+ *
+ * @param res
+ * visible start residue
+ * @return left column of panel res will be located in
+ */
+ private int calcWrappedStartResidue(int res)
+ {
+ int oldStartRes = startRes;
+ int width = getViewportWidth();
boolean up = res < oldStartRes;
int widthsToScroll = Math.abs((res - oldStartRes) / width);
{
newStartRes = 0;
}
-
- setStartRes(newStartRes);
-
- return true;
+ return newStartRes;
}
/**
* Scroll so that (x,y) is visible. Fires a property change event.
*
* @param x
- * x position in alignment
+ * x position in alignment (absolute position)
* @param y
- * y position in alignment
+ * y position in alignment (absolute position)
*/
public void scrollToVisible(int x, int y)
{
{
scrollUp(false);
}
-
+
HiddenColumns hidden = al.getHiddenColumns();
while (x < hidden.adjustForHiddenColumns(startRes))
{
}
/**
+ * Set the viewport location so that a position is visible
+ *
+ * @param x
+ * column to be visible: absolute position in alignment
+ * @param y
+ * row to be visible: absolute position in alignment
+ */
+ public boolean setViewportLocation(int x, int y)
+ {
+ boolean changedLocation = false;
+
+ // convert the x,y location to visible coordinates
+ int visX = al.getHiddenColumns().findColumnPosition(x);
+ int visY = al.getHiddenSequences().findIndexWithoutHiddenSeqs(y);
+
+ // if (vis_x,vis_y) is already visible don't do anything
+ if (startRes > visX || visX > endRes
+ || startSeq > visY && visY > endSeq)
+ {
+ int[] old = new int[] { startRes, startSeq };
+ int[] newresseq;
+ if (wrappedMode)
+ {
+ int newstartres = calcWrappedStartResidue(visX);
+ setStartRes(newstartres);
+ newresseq = new int[] { startRes, startSeq };
+ }
+ else
+ {
+ // set the viewport x location to contain vis_x
+ int newstartres = visX;
+ int width = getViewportWidth();
+ if (newstartres + width - 1 > getVisibleAlignmentWidth() - 1)
+ {
+ newstartres = getVisibleAlignmentWidth() - width;
+ }
+ updateStartEndRes(newstartres, newstartres + width - 1);
+
+ // set the viewport y location to contain vis_y
+ int newstartseq = visY;
+ int height = getViewportHeight();
+ if (newstartseq + height - 1 > getVisibleAlignmentHeight() - 1)
+ {
+ newstartseq = getVisibleAlignmentHeight() - height;
+ }
+ updateStartEndSeq(newstartseq, newstartseq + height - 1);
+
+ newresseq = new int[] { startRes, startSeq };
+ }
+ changedLocation = true;
+ changeSupport.firePropertyChange(MOVE_VIEWPORT, old, newresseq);
+ }
+ return changedLocation;
+ }
+
+ /**
* Adjust sequence position for page up. Fires a property change event.
*/
public void pageUp()
/**
*
* @param entry
- * UniportEntry
+ * UniprotEntry
* @return The accession id(s) and name(s) delimited by '|'.
*/
public static String getUniprotEntryId(UniprotEntry entry)
{
StringBuilder name = new StringBuilder(32);
- // name.append("UniProt/Swiss-Prot");
- // use 'canonicalised' name for optimal id matching
- name.append(DBRefSource.UNIPROT);
- for (String accessionId : entry.getAccession())
- {
- name.append(BAR_DELIMITER);
- name.append(accessionId);
- }
for (String n : entry.getName())
{
- name.append(BAR_DELIMITER);
+ if (name.length() > 0)
+ {
+ name.append(BAR_DELIMITER);
+ }
name.append(n);
}
return name.toString();
sq.checkValidRange();
assertEquals(22, sq.getEnd());
}
+
+ @Test(groups = { "Functional" })
+ public void testDeleteChars_withGaps()
+ {
+ /*
+ * delete gaps only
+ */
+ SequenceI sq = new Sequence("test/8-10", "A-B-C");
+ sq.createDatasetSequence();
+ assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+ sq.deleteChars(1, 2); // delete first gap
+ assertEquals("AB-C", sq.getSequenceAsString());
+ assertEquals(8, sq.getStart());
+ assertEquals(10, sq.getEnd());
+ assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+
+ /*
+ * delete gaps and residues at start (no new dataset sequence)
+ */
+ sq = new Sequence("test/8-10", "A-B-C");
+ sq.createDatasetSequence();
+ sq.deleteChars(0, 3); // delete A-B
+ assertEquals("-C", sq.getSequenceAsString());
+ assertEquals(10, sq.getStart());
+ assertEquals(10, sq.getEnd());
+ assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+
+ /*
+ * delete gaps and residues at end (no new dataset sequence)
+ */
+ sq = new Sequence("test/8-10", "A-B-C");
+ sq.createDatasetSequence();
+ sq.deleteChars(2, 5); // delete B-C
+ assertEquals("A-", sq.getSequenceAsString());
+ assertEquals(8, sq.getStart());
+ assertEquals(8, sq.getEnd());
+ assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
+
+ /*
+ * delete gaps and residues internally (new dataset sequence)
+ * first delete from gap to residue
+ */
+ sq = new Sequence("test/8-10", "A-B-C");
+ sq.createDatasetSequence();
+ sq.deleteChars(1, 3); // delete -B
+ assertEquals("A-C", sq.getSequenceAsString());
+ assertEquals(8, sq.getStart());
+ assertEquals(9, sq.getEnd());
+ assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
+ assertEquals(8, sq.getDatasetSequence().getStart());
+ assertEquals(9, sq.getDatasetSequence().getEnd());
+
+ /*
+ * internal delete from gap to gap
+ */
+ sq = new Sequence("test/8-10", "A-B-C");
+ sq.createDatasetSequence();
+ sq.deleteChars(1, 4); // delete -B-
+ assertEquals("AC", sq.getSequenceAsString());
+ assertEquals(8, sq.getStart());
+ assertEquals(9, sq.getEnd());
+ assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
+ assertEquals(8, sq.getDatasetSequence().getStart());
+ assertEquals(9, sq.getDatasetSequence().getEnd());
+
+ /*
+ * internal delete from residue to residue
+ */
+ sq = new Sequence("test/8-10", "A-B-C");
+ sq.createDatasetSequence();
+ sq.deleteChars(2, 3); // delete B
+ assertEquals("A--C", sq.getSequenceAsString());
+ assertEquals(8, sq.getStart());
+ assertEquals(9, sq.getEnd());
+ assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
+ assertEquals(8, sq.getDatasetSequence().getStart());
+ assertEquals(9, sq.getDatasetSequence().getEnd());
+ }
}
vr.setEndSeq(al.getHeight());
assertEquals(vr.getEndSeq(), al.getHeight() - 1);
- // vr.setEndRes(al.getHeight() - 1);
vr.setEndSeq(al.getHeight() - 1);
assertEquals(vr.getEndSeq(), al.getHeight() - 1);
}
}
@Test(groups = { "Functional" })
+ public void testSetStartResAndSeq()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ vr.setViewportHeight(10);
+ vr.setStartResAndSeq(3, 6);
+ assertEquals(vr.getStartRes(), 3);
+ assertEquals(vr.getStartSeq(), 6);
+ assertEquals(vr.getEndRes(), 3 + vr.getViewportWidth() - 1);
+ assertEquals(vr.getEndSeq(), 6 + vr.getViewportHeight() - 1);
+
+ vr.setStartResAndSeq(10, 25);
+ assertEquals(vr.getStartRes(), 10);
+ assertEquals(vr.getStartSeq(), 19);
+ assertEquals(vr.getEndRes(), 10 + vr.getViewportWidth() - 1);
+ assertEquals(vr.getEndSeq(), 19 + vr.getViewportHeight() - 1);
+ }
+
+ @Test(groups = { "Functional" })
public void testSetViewportHeight()
{
ViewportRanges vr = new ViewportRanges(al);
assertEquals(vr.getEndRes(), 52);
}
- // leave until JAL-2388 is merged and we can do without viewport
- /*@Test(groups = { "Functional" })
+ @Test(groups = { "Functional" })
public void testScrollToVisible()
{
ViewportRanges vr = new ViewportRanges(al);
vr.setViewportStartAndWidth(12,5);
vr.setViewportStartAndHeight(10,6);
- vr.scrollToVisible(13,14)
+ vr.scrollToVisible(13, 14);
// no change
assertEquals(vr.getStartRes(), 12);
assertEquals(vr.getStartSeq(), 6);
// test for hidden columns too
- }*/
+ al.getHiddenColumns().hideColumns(1, 3);
+ vr.scrollToVisible(13, 3);
+ assertEquals(vr.getStartRes(), 6);
+ assertEquals(vr.getStartSeq(), 3);
+
+ vr.scrollToVisible(2, 9);
+ assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getStartSeq(), 4);
+ }
@Test(groups = { "Functional" })
public void testEventFiring()
// one event fired when startRes is called with new value
vr.setStartRes(4);
- assertTrue(l.verify(1, Arrays.asList("startres")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
l.reset();
// no event fired for same value
l.reset();
vr.setStartSeq(4);
- assertTrue(l.verify(1, Arrays.asList("startseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
l.reset();
vr.setStartSeq(4);
l.reset();
vr.setEndSeq(10);
- assertTrue(l.verify(1, Arrays.asList("startseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
l.reset();
vr.setEndSeq(10);
l.reset();
vr.setStartEndRes(2, 15);
- assertTrue(l.verify(1, Arrays.asList("startres")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
l.reset();
vr.setStartEndRes(2, 15);
// check new value fired by event is corrected startres
vr.setStartEndRes(-1, 5);
- assertTrue(l.verify(1, Arrays.asList("startres"), Arrays.asList(0)));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES),
+ Arrays.asList(0)));
l.reset();
// check new value fired by event is corrected endres
vr.setStartEndRes(0, -1);
- assertTrue(l.verify(1, Arrays.asList("endres"), Arrays.asList(0)));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES),
+ Arrays.asList(0)));
l.reset();
vr.setStartEndSeq(2, 15);
- assertTrue(l.verify(1, Arrays.asList("startseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
l.reset();
vr.setStartEndSeq(2, 15);
// check new value fired by event is corrected startseq
vr.setStartEndSeq(-1, 5);
- assertTrue(l.verify(1, Arrays.asList("startseq"), Arrays.asList(0)));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ),
+ Arrays.asList(0)));
l.reset();
// check new value fired by event is corrected endseq
vr.setStartEndSeq(0, -1);
- assertTrue(l.verify(1, Arrays.asList("endseq"), Arrays.asList(0)));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ),
+ Arrays.asList(0)));
l.reset();
// reset for later tests
// test viewport height and width setting triggers event
vr.setViewportHeight(10);
- assertTrue(l.verify(1, Arrays.asList("endseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
l.reset();
vr.setViewportWidth(18);
- assertTrue(l.verify(1, Arrays.asList("endres")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES)));
l.reset();
// already has seq start set to 2, so triggers endseq
vr.setViewportStartAndHeight(2, 16);
- assertTrue(l.verify(1, Arrays.asList("endseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
l.reset();
vr.setViewportStartAndWidth(1, 14);
- assertTrue(l.verify(1, Arrays.asList("startres")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
l.reset();
// test page up/down triggers event
vr.pageUp();
- assertTrue(l.verify(1, Arrays.asList("startseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
l.reset();
vr.pageDown();
- assertTrue(l.verify(1, Arrays.asList("startseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
l.reset();
// test scrolling triggers event
vr.scrollUp(true);
- assertTrue(l.verify(1, Arrays.asList("startseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
l.reset();
vr.scrollUp(false);
- assertTrue(l.verify(1, Arrays.asList("startseq")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
l.reset();
vr.scrollRight(true);
- assertTrue(l.verify(1, Arrays.asList("startres")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
l.reset();
vr.scrollRight(false);
- assertTrue(l.verify(1, Arrays.asList("startres")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
l.reset();
vr.scrollToVisible(10, 10);
assertTrue(l.verify(4,
- Arrays.asList("startseq", "startseq", "startseq", "startseq")));
+ Arrays.asList(ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ,
+ ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ)));
l.reset();
/*
l.reset();
vr.scrollToWrappedVisible(25);
- assertTrue(l.verify(1, Arrays.asList("startres")));
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
+ l.reset();
+
+ // test setStartResAndSeq triggers one event
+ vr.setStartResAndSeq(5, 7);
+ assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRESANDSEQ),
+ Arrays.asList(5, 7)));
+
+ l.reset();
}
@Test(groups = { "Functional" })
assertEquals(vr.getStartSeq(), 1);
assertEquals(vr.getStartRes(), 43);
}
+
+ @Test(groups = { "Functional" })
+ public void testSetViewportLocation()
+ {
+ AlignmentI al2 = gen.generate(60, 80, 1, 0, 0);
+
+ ViewportRanges vr = new ViewportRanges(al2);
+
+ // start with viewport on 5-14
+ vr.setViewportStartAndWidth(5, 10);
+ assertEquals(vr.getStartRes(), 5);
+ assertEquals(vr.getEndRes(), 14);
+
+ vr.setViewportStartAndHeight(3, 13);
+ assertEquals(vr.getStartSeq(), 3);
+ assertEquals(vr.getEndSeq(), 15);
+
+ // set location to (8,5) - no change
+ vr.setViewportLocation(8, 5);
+ assertEquals(vr.getStartRes(), 5);
+ assertEquals(vr.getEndRes(), 14);
+ assertEquals(vr.getStartSeq(), 3);
+ assertEquals(vr.getEndSeq(), 15);
+
+ // set location to (40,50) - change to top left (40,50)
+ vr.setViewportLocation(40, 50);
+ assertEquals(vr.getStartRes(), 40);
+ assertEquals(vr.getEndRes(), 49);
+ assertEquals(vr.getStartSeq(), 50);
+ assertEquals(vr.getEndSeq(), 62);
+
+ // set location past end of alignment - resets to leftmost pos
+ vr.setViewportLocation(63, 85);
+ assertEquals(vr.getStartRes(), 50);
+ assertEquals(vr.getEndRes(), 59);
+ assertEquals(vr.getStartSeq(), 67);
+ assertEquals(vr.getEndSeq(), 79);
+
+ // hide some columns
+ al2.getHiddenColumns().hideColumns(20, 50);
+ vr.setViewportLocation(55, 4);
+ assertEquals(vr.getStartRes(), 19);
+ assertEquals(vr.getEndRes(), 28);
+ assertEquals(vr.getStartSeq(), 4);
+ assertEquals(vr.getEndSeq(), 16);
+
+ // hide some sequences
+ al2.getHiddenSequences().hideSequence(al2.getSequenceAt(3));
+ al2.getHiddenSequences().hideSequence(al2.getSequenceAt(4));
+ vr.setViewportLocation(17, 5);
+ assertEquals(vr.getStartRes(), 17);
+ assertEquals(vr.getEndRes(), 26);
+ assertEquals(vr.getStartSeq(), 3);
+ assertEquals(vr.getEndSeq(), 15);
+
+ // set wrapped mode
+ vr.setWrappedMode(true);
+ vr.setViewportLocation(1, 8);
+ assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getEndRes(), 9);
+ assertEquals(vr.getStartSeq(), 3);
+ assertEquals(vr.getEndSeq(), 15);
+
+ // try further down the alignment
+ vr.setViewportLocation(57, 5);
+ assertEquals(vr.getStartRes(), 20);
+ assertEquals(vr.getEndRes(), 29);
+ assertEquals(vr.getStartSeq(), 3);
+ assertEquals(vr.getEndSeq(), 15);
+ }
}
// mock listener for property change events
{
firecount++;
events.add(evt.getPropertyName());
- newvalues.add((Integer) evt.getNewValue());
+ if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ newvalues.add(((int[]) evt.getNewValue())[0]);
+ newvalues.add(((int[]) evt.getNewValue())[1]);
+ }
+ else
+ {
+ newvalues.add((Integer) evt.getNewValue());
+ }
}
public boolean verify(int count, List<String> eventslist,
new StringReader(UNIPROT_XML)).get(0);
/*
- * name formatted as source | accession ids | names
- * source database converted to Jalview canonical name
+ * name formatted with Uniprot Entry name
*/
- String expectedName = "UNIPROT|A9CKP4|A9CKP5|A9CKP4_AGRT5|A9CKP4_AGRT6";
- assertEquals(expectedName, Uniprot.getUniprotEntryId(entry));
+ String expectedName = "A9CKP4_AGRT5|A9CKP4_AGRT6";
+ assertEquals(expectedName,
+ Uniprot.getUniprotEntryId(entry));
}
/**