Merge branch 'features/JAL-2320_closeChimeraAction' into releases/Release_2_10_Branch Release_2_10_1
authorJim Procter <jprocter@issues.jalview.org>
Wed, 30 Nov 2016 15:51:54 +0000 (15:51 +0000)
committerJim Procter <jprocter@issues.jalview.org>
Wed, 30 Nov 2016 15:51:54 +0000 (15:51 +0000)
also tidied up javadoc

139 files changed:
.classpath
AUTHORS
RELEASE
THIRDPARTYLIBS
appletlib/JmolApplet-14.2.14_2015.06.11.jar [deleted file]
appletlib/JmolApplet-14.6.4_2016.10.26.jar [new file with mode: 0644]
build.xml
examples/appletDeployment.html
examples/applets.html
examples/embedded.html
examples/embeddedWJmol.html
examples/formComplete.html
examples/javascript/facebox-1.3.js [new file with mode: 0644]
examples/javascriptLaunch.html
examples/linkedapplets_ng.html
help/help.jhm
help/helpTOC.xml
help/html/colourSchemes/abovePID.html
help/html/features/chimera.html
help/html/features/clarguments.html
help/html/features/jmol.html
help/html/features/search.html
help/html/io/exportseqreport.html
help/html/keys.html
help/html/menus/alignmentMenu.html
help/html/menus/alwselect.html
help/html/releases.html
help/html/webServices/dbreffetcher.html
help/html/webServices/urllinks.html
help/html/whatsNew.html
lib/Jmol-14.2.14_2015.06.11.jar [deleted file]
lib/Jmol-14.6.4_2016.10.26.jar [new file with mode: 0644]
nbproject/project.properties
resources/authors.props
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/ext/edu/ucsf/rbvi/strucviz2/ChimUtils.java
src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java
src/ext/edu/ucsf/rbvi/strucviz2/ChimeraModel.java
src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java
src/ext/edu/ucsf/rbvi/strucviz2/StructureSettings.java
src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java
src/jalview/analysis/AAFrequency.java
src/jalview/analysis/Finder.java
src/jalview/api/AlignViewControllerI.java
src/jalview/api/AlignViewportI.java
src/jalview/api/FeatureRenderer.java
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/AlignViewport.java
src/jalview/appletgui/AlignmentPanel.java
src/jalview/appletgui/AppletJmol.java
src/jalview/appletgui/AppletJmolBinding.java
src/jalview/appletgui/ExtJmol.java
src/jalview/appletgui/FeatureRenderer.java
src/jalview/appletgui/Finder.java
src/jalview/appletgui/SeqCanvas.java
src/jalview/appletgui/SeqPanel.java
src/jalview/bin/Jalview.java
src/jalview/controller/AlignViewController.java
src/jalview/datamodel/AlignedCodonFrame.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/PDBEntry.java
src/jalview/datamodel/Profile.java
src/jalview/datamodel/ProfileI.java
src/jalview/datamodel/Profiles.java [new file with mode: 0644]
src/jalview/datamodel/ProfilesI.java [new file with mode: 0644]
src/jalview/datamodel/ResidueCount.java
src/jalview/datamodel/SearchResultMatchI.java [new file with mode: 0644]
src/jalview/datamodel/SearchResults.java
src/jalview/datamodel/SearchResultsI.java [new file with mode: 0644]
src/jalview/datamodel/SequenceFeature.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/ext/android/ContainerHelpers.java
src/jalview/ext/android/SparseIntArray.java
src/jalview/ext/android/SparseShortArray.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/jmol/JmolParser.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AppJmol.java
src/jalview/gui/AppJmolBinding.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/Finder.java
src/jalview/gui/IdPanel.java
src/jalview/gui/JalviewChimeraBindingModel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/SeqPanel.java
src/jalview/gui/StructureChooser.java
src/jalview/gui/StructureViewerBase.java
src/jalview/io/BioJsHTMLOutput.java
src/jalview/io/HTMLOutput.java
src/jalview/io/HtmlSvgOutput.java
src/jalview/io/JnetAnnotationMaker.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/schemes/Blosum62ColourScheme.java
src/jalview/schemes/ColourSchemeI.java
src/jalview/schemes/FollowerColourScheme.java
src/jalview/schemes/PIDColourScheme.java
src/jalview/schemes/ResidueColourScheme.java
src/jalview/structure/SequenceListener.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/structures/models/AAStructureBindingModel.java
src/jalview/util/MappingUtils.java
src/jalview/util/SparseCount.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/workers/ConsensusThread.java
src/jalview/ws/sifts/SiftsClient.java
test/jalview/analysis/AAFrequencyTest.java
test/jalview/analysis/AlignmentUtilsTests.java
test/jalview/analysis/ConservationTest.java
test/jalview/analysis/FinderTest.java [new file with mode: 0644]
test/jalview/analysis/scoremodels/FeatureScoreModelTest.java
test/jalview/controller/AlignViewControllerTest.java
test/jalview/datamodel/MatchTest.java
test/jalview/datamodel/ResidueCountTest.java
test/jalview/datamodel/SearchResultsTest.java
test/jalview/datamodel/SequenceFeatureTest.java
test/jalview/ext/android/SparseIntArrayTest.java
test/jalview/ext/android/SparseShortArrayTest.java
test/jalview/gui/AlignViewportTest.java
test/jalview/io/BioJsHTMLOutputTest.java
test/jalview/io/SequenceAnnotationReportTest.java
test/jalview/schemes/ResidueColourSchemeTest.java
test/jalview/structures/models/AAStructureBindingModelTest.java
test/jalview/util/FormatTest.java
test/jalview/util/MappingUtilsTest.java
test/jalview/util/PlatformTest.java
test/jalview/util/SparseCountTest.java
test/jalview/ws/sifts/SiftsClientTest.java
utils/InstallAnywhere/Jalview.iap_xml

index 6583992..8aef745 100644 (file)
@@ -64,7 +64,7 @@
        <classpathentry kind="lib" path="lib/jetty-http-9.2.10.v20150310.jar"/>
        <classpathentry kind="lib" path="lib/jetty-io-9.2.10.v20150310.jar"/>
        <classpathentry kind="lib" path="lib/java-json.jar"/>
-       <classpathentry kind="lib" path="lib/Jmol-14.2.14_2015.06.11.jar"/>
+       <classpathentry kind="lib" path="lib/Jmol-14.6.4_2016.10.26.jar"/>
        <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"/>
diff --git a/AUTHORS b/AUTHORS
index f0b4787..1bfc734 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,15 +7,16 @@ or might otherwise be considered author of Jalview.
 The people listed below are 'The Jalview Authors', who collectively
 own the copyright to the Jalview source code and permit it to be released under GPL.
 
-This is the authoritative list. It was correct on 6th Oct 2016.
+This is the authoritative list. It was correct on 23rd November 2016.
 If you are releasing a version of Jalview, please make sure any
 statement of authorship in the GUI reflects the list shown here.
 In particular, check the resources/authors.props file ! 
 
 Jim Procter
-Andrew Waterhouse
 Mungo Carstairs
 Tochukwu 'Charles' Ofoegbu
+Kira Mourao
+Andrew Waterhouse
 Jan Engelhardt
 Lauren Lui
 Anne Menard
diff --git a/RELEASE b/RELEASE
index 702d6e7..9bc5817 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,2 +1,2 @@
-jalview.release=Release_2_10_0_Branch
-jalview.version=2.10.0b1
+jalview.release=releases/Release_2_10_1_Branch
+jalview.version=2.10.1
index 31ad2f5..e0be904 100644 (file)
@@ -6,11 +6,14 @@ A number of sources have also been adapted for incorporation into Jalview's sour
 
 ext.edu.ucsf.rbvi.strucviz2 includes sources originally developed by Scooter Morris and Nadezhda Doncheva for the Cytoscape StructureViz2 plugin. It is released under the Berkley license and we hereby acknowledge its original copyright is held by the UCSF Computer Graphics Laboratory
  and the software was developed with support by the NIH National Center for Research Resources, grant P41-RR01081. 
+ jalview.ext.android includes code taken from the Android Open Source Project (https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util).
+ The Apache 2.0 Licence (http://www.apache.org/licenses/LICENSE-2.0) is acknowledged in the source code.
 
-Licencing information for each library is given below:
+Licensing information for each library is given below:
 
 JGoogleAnalytics_0.3.jar       APL 2.0 License - http://code.google.com/p/jgoogleanalytics/
-Jmol-14.2.14_2015.06.11.jar    GPL/LGPLv2 http://sourceforge.net/projects/jmol/files/
+Jmol-14.6.4_2016.10.26.jar     GPL/LGPLv2 http://sourceforge.net/projects/jmol/files/
 VARNAv3-93.jar GPL licenced software by K�vin Darty, Alain Denise and Yann Ponty. http://varna.lri.fr
 activation.jar 
 apache-mime4j-0.6.jar
@@ -58,4 +61,5 @@ Additional dependencies
 examples/javascript/deployJava.js : http://java.com/js/deployJava.js
 examples/javascript/jquery*.js : BSD license
 examples/javascript/jshashtable-2.1.js : Apache License
+examples/javascript/facebox-1.3.js : MTI License - http://www.opensource.org/licenses/mit-license.php
 
diff --git a/appletlib/JmolApplet-14.2.14_2015.06.11.jar b/appletlib/JmolApplet-14.2.14_2015.06.11.jar
deleted file mode 100644 (file)
index 5d6338c..0000000
Binary files a/appletlib/JmolApplet-14.2.14_2015.06.11.jar and /dev/null differ
diff --git a/appletlib/JmolApplet-14.6.4_2016.10.26.jar b/appletlib/JmolApplet-14.6.4_2016.10.26.jar
new file mode 100644 (file)
index 0000000..e5c312c
Binary files /dev/null and b/appletlib/JmolApplet-14.6.4_2016.10.26.jar differ
index 1d4878b..8d27614 100755 (executable)
--- a/build.xml
+++ b/build.xml
     <property name="packageDir" value="dist" />
     <property name="outputJar" value="jalview.jar" />
     <!-- Jalview Applet JMol Jar Dependency -->
-    <property name="jmolJar" value="JmolApplet-14.2.14_2015.06.11.jar" />
+    <property name="jmolJar" value="JmolApplet-14.6.4_2016.10.26.jar" />
     <property name="varnaJar" value="VARNAv3-93.jar" />
     <property name="jsoup" value="jsoup-1.8.1.jar" />
     <property name="jsonSimple" value="json_simple-1.1.jar" />
   <!-- temporary copy of source to update timestamps -->
   <copy todir="_sourcedist">
     <fileset dir=".">
+      <exclude name=".*" />
+      <exclude name="**/.*" />
+      <exclude name="*.class" />
+      <exclude name="**/*.class" />
       <include name="LICENSE" />
       <include name="README" />
       <include name="build.xml" />
       <exclude name="utils/InstallAnywhere/**Build.iap_xml" />
       <exclude name="utils/InstallAnywhere/**Build*/**" />
       <exclude name="utils/InstallAnywhere/**Build*/**" />
+      <exclude name="utils/InstallAnywhere/.build*.*/**" />
       <exclude name="utils/InstallAnywhere/**locale*" />
       <exclude name="utils/InstallAnywhere/**locale*/**" />
+      <exclude name="utils/InstallAnywhere/**locale*/**" />
       <include name="${schemaDir}/**/*" />
       <include name="utils/**/*" />
       <include name="${docDir}/**/*" />
index 7fcca00..7b4daee 100644 (file)
@@ -33,7 +33,7 @@
     <td>Main Jalview Applet Jar</td>
   </tr>
   <tr>
-    <td><a href="http://www.jalview.org/builds/develop/examples/JmolApplet-14.2.14_2015.06.11.jar">JmolApplet-14.2.14_2015.06.11.jar</a> </td>
+    <td><a href="http://www.jalview.org/builds/develop/examples/JmolApplet-14.6.4_2016.10.26.jar">JmolApplet-14.6.4_2016.10.26.jar</a> </td>
     <td>Jmol Applet Jar</td>
   </tr>
   <tr>
@@ -48,7 +48,7 @@
 
 <p>To run Jalview applet in your web page download the Jars listed above. The snippet below shows a minimal code for embedding Jalview applet into a web page.    
 <pre><code>
-&lt;applet code="jalview.bin.JalviewLite" width="756" height="560" archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar"&gt;
+&lt;applet code="jalview.bin.JalviewLite" width="756" height="560" archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar"&gt;
        &lt;param name="permissions" value="sandbox" /&gt;
        &lt;param name="file" value="plantfdx.fa" /&gt;
        &lt;param name="features" value="plantfdx.features" /&gt;
index 1f65565..d997f14 100644 (file)
@@ -41,7 +41,7 @@ Try out JalviewLite by pressing one of the buttons below.
       <td width="10%" valign="center">
       <applet
        code="jalview.bin.JalviewLite" width="140" height="35"
-       archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">  
+       archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">  
        <param name="permissions" value="sandbox"/>
        <param name="file" value="uniref50.fa"/>
        <param name="treeFile" value="ferredoxin.nw"/>
@@ -64,7 +64,7 @@ Try out JalviewLite by pressing one of the buttons below.
     <tr>
       <td width="10%" valign="center"><applet
    code="jalview.bin.JalviewLite" width="140" height="35"
-   archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="permissions" value="sandbox"/>
 <param name="file" value="uniref50.fa"/>
 <param name="features" value="exampleFeatures.txt"/>
@@ -89,7 +89,7 @@ Try out JalviewLite by pressing one of the buttons below.
     <tr>
       <td width="10%" valign="center"><applet
    code="jalview.bin.JalviewLite" width="140" height="35"
-   archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="permissions" value="sandbox"/>
 <param name="file" value="uniref50.fa"/>
 <param name="showFullId" value="false"/>
@@ -116,7 +116,7 @@ Try out JalviewLite by pressing one of the buttons below.
     <tr>
       <td width="10%" valign="center"><applet
    code="jalview.bin.JalviewLite" width="140" height="35"
-   archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="permissions" value="sandbox"/>
 <param name="file" value="jpred_msa.fasta"/>
 <param name="jnetfile" value="jpred_msa.seq.concise"/>
@@ -147,7 +147,7 @@ Try out JalviewLite by pressing one of the buttons below.
     <tr>
       <td width="10%" valign="center"><applet
    code="jalview.bin.JalviewLite" width="140" height="35"
-   archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="permissions" value="sandbox"/>
 <param name="file" value="RF00031_folded.stk"/>
 <param name="showFullId" value="false"/>
@@ -171,7 +171,7 @@ Try out JalviewLite by pressing one of the buttons below.
       <td width="10%" valign="center">
 <applet
    code="jalview.bin.JalviewLite" width="140" height="35"
-   archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="permissions" value="sandbox"/>
 <param name="file2" value="estrogenReceptorCdna_frag.fa"/>
 <param name="file" value="estrogenReceptorProtein_frag.fa"/>
index 0d5ddf3..0cea17d 100644 (file)
@@ -40,7 +40,7 @@
   <a href="view-source:http://www.jalview.org/builds/develop/examples/embedded.html" target="_blank">View the source code for this example here</a> (If the link doesn't work on your browser try going to <a href="http://www.jalview.org/builds/develop/examples/embedded.html">this page</a> and viewing the page source manually).<p>
   <applet
    code="jalview.bin.JalviewLite" width="756" height="560"
-   archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="permissions" value="sandbox"/>
 <param name="file" value="plantfdx.fa"/>
 <param name="features" value="plantfdx.features"/>
index 501c20e..6fdcc07 100644 (file)
@@ -211,7 +211,7 @@ jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","ajaxPageState":
 <script language="JavaScript">
 // instead of this, we use a custom JmolApplet spec
 // jmolInitialize('jmol');
-jmolInitialize("","JmolApplet-14.2.14_2015.06.11.jar");
+jmolInitialize("","JmolApplet-14.6.4_2016.10.26.jar");
 </script>
 <script>
  var loglevel=1;
@@ -242,7 +242,7 @@ jmolInitialize("","JmolApplet-14.2.14_2015.06.11.jar");
  var _jvA=new Object();
  _jvA.attributes = {
   code : 'jalview.bin.JalviewLite',
-  archive : 'jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar',
+  archive : 'jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar',
   width : '500',
   height : '350',
   mayscript : 'True',
@@ -295,7 +295,7 @@ jmolInitialize("","JmolApplet-14.2.14_2015.06.11.jar");
 </div>
 <div>
 <applet
-   code="jalview.bin.JalviewLite" width="500" height="350" id="jvA" mayscript="mayscript" archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   code="jalview.bin.JalviewLite" width="500" height="350" id="jvA" mayscript="mayscript" archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="permissions" value="sandbox"/>
 <param name="java_arguments" value="-Xmx256m"/>
 <param name="externalstructureviewer" value="true"/>
index 9e89990..65a3a45 100644 (file)
@@ -36,7 +36,7 @@ instance on the page.</p>
   <a href="view-source:http://www.jalview.org/builds/develop/examples/formComplete.html" target="_blank">View the source here to see how it has been done</a>  (If the link doesn't work on your browser try going to <a href="http://www.jalview.org/builds/develop/examples/formComplete.html">this page</a> and viewing the page source manually).<br/>
 <a name="api">View the full <a href="javascript:doSubmit('jalviewLiteJs')">JalviewLite API documentation</a>.</a>
 <applet code="jalview.bin.JalviewLite" width="0" height="0"
-       archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar" name="Jalview">
+       archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar" name="Jalview">
   
   <param name="file" value="plantfdx.fa"/>
   <param name="features" value="plantfdx.features"/>
diff --git a/examples/javascript/facebox-1.3.js b/examples/javascript/facebox-1.3.js
new file mode 100644 (file)
index 0000000..ad45310
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Facebox (for jQuery)
+ * version: 1.2 (05/05/2008)
+ * @requires jQuery v1.2 or later
+ *
+ * Examples at http://famspam.com/facebox/
+ *
+ * Licensed under the MIT:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *
+ * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
+ *
+ * Usage:
+ *
+ *  jQuery(document).ready(function() {
+ *    jQuery('a[rel*=facebox]').facebox()
+ *  })
+ *
+ *  <a href="#terms" rel="facebox">Terms</a>
+ *    Loads the #terms div in the box
+ *
+ *  <a href="terms.html" rel="facebox">Terms</a>
+ *    Loads the terms.html page in the box
+ *
+ *  <a href="terms.png" rel="facebox">Terms</a>
+ *    Loads the terms.png image in the box
+ *
+ *
+ *  You can also use it programmatically:
+ *
+ *    jQuery.facebox('some html')
+ *    jQuery.facebox('some html', 'my-groovy-style')
+ *
+ *  The above will open a facebox with "some html" as the content.
+ *
+ *    jQuery.facebox(function($) {
+ *      $.get('blah.html', function(data) { $.facebox(data) })
+ *    })
+ *
+ *  The above will show a loading screen before the passed function is called,
+ *  allowing for a better ajaxy experience.
+ *
+ *  The facebox function can also display an ajax page, an image, or the contents of a div:
+ *
+ *    jQuery.facebox({ ajax: 'remote.html' })
+ *    jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style')
+ *    jQuery.facebox({ image: 'stairs.jpg' })
+ *    jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style')
+ *    jQuery.facebox({ div: '#box' })
+ *    jQuery.facebox({ div: '#box' }, 'my-groovy-style')
+ *
+ *  Want to close the facebox?  Trigger the 'close.facebox' document event:
+ *
+ *    jQuery(document).trigger('close.facebox')
+ *
+ *  Facebox also has a bunch of other hooks:
+ *
+ *    loading.facebox
+ *    beforeReveal.facebox
+ *    reveal.facebox (aliased as 'afterReveal.facebox')
+ *    init.facebox
+ *    afterClose.facebox
+ *
+ *  Simply bind a function to any of these hooks:
+ *
+ *   $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })
+ *
+ */
+(function($) {
+  $.facebox = function(data, klass) {
+    $.facebox.loading()
+
+    if (data.ajax) fillFaceboxFromAjax(data.ajax, klass)
+    else if (data.image) fillFaceboxFromImage(data.image, klass)
+    else if (data.div) fillFaceboxFromHref(data.div, klass)
+    else if ($.isFunction(data)) data.call($)
+    else $.facebox.reveal(data, klass)
+  }
+
+  /*
+   * Public, $.facebox methods
+   */
+
+  $.extend($.facebox, {
+    settings: {
+      opacity      : 0.2,
+      overlay      : true,
+      loadingImage : 'https://raw.githubusercontent.com/jalview/biojson/gh-pages/images/loading.gif',
+      closeImage   : 'https://raw.githubusercontent.com/jalview/biojson/gh-pages/images/cancel.png',
+      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],
+      faceboxHtml  : '\
+    <div id="facebox" style="display:none;"> \
+      <div class="popup"> \
+        <div class="content"> \
+        </div> \
+        <a href="#" class="close"><img src="https://raw.githubusercontent.com/jalview/biojson/gh-pages/images/cancel.png" title="close" class="close_image" /></a> \
+      </div> \
+    </div>'
+    },
+
+    loading: function() {
+      init()
+      if ($('#facebox .loading').length == 1) return true
+      showOverlay()
+
+      $('#facebox .content').empty()
+      $('#facebox .body').children().hide().end().
+        append('<div class="loading"><img src="'+$.facebox.settings.loadingImage+'"/></div>')
+
+      $('#facebox').css({
+        top:   getPageScroll()[1] + (getPageHeight() / 10),
+        left:  $(window).width() / 2 - 205
+      }).show()
+
+      $(document).bind('keydown.facebox', function(e) {
+        if (e.keyCode == 27) $.facebox.close()
+        return true
+      })
+      $(document).trigger('loading.facebox')
+    },
+
+    reveal: function(data, klass) {
+      $(document).trigger('beforeReveal.facebox')
+      if (klass) $('#facebox .content').addClass(klass)
+      $('#facebox .content').append('<pre><code>'+JSON.stringify(JSON.parse(data),null,4)+'</pre></code>')
+      $('#facebox .loading').remove()
+      $('#facebox .body').children().fadeIn('normal')
+      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2))
+      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')
+    },
+
+    close: function() {
+      $(document).trigger('close.facebox')
+      return false
+    }
+  })
+
+  /*
+   * Public, $.fn methods
+   */
+
+  $.fn.facebox = function(settings) {
+    if ($(this).length == 0) return
+
+    init(settings)
+
+    function clickHandler() {
+      $.facebox.loading(true)
+
+      // support for rel="facebox.inline_popup" syntax, to add a class
+      // also supports deprecated "facebox[.inline_popup]" syntax
+      var klass = this.rel.match(/facebox\[?\.(\w+)\]?/)
+      if (klass) klass = klass[1]
+
+      fillFaceboxFromHref(this.href, klass)
+      return false
+    }
+
+    return this.bind('click.facebox', clickHandler)
+  }
+
+  /*
+   * Private methods
+   */
+
+  // called one time to setup facebox on this page
+  function init(settings) {
+    if ($.facebox.settings.inited) return true
+    else $.facebox.settings.inited = true
+
+    $(document).trigger('init.facebox')
+    makeCompatible()
+
+    var imageTypes = $.facebox.settings.imageTypes.join('|')
+    $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i')
+
+    if (settings) $.extend($.facebox.settings, settings)
+    $('body').append($.facebox.settings.faceboxHtml)
+
+    var preload = [ new Image(), new Image() ]
+    preload[0].src = $.facebox.settings.closeImage
+    preload[1].src = $.facebox.settings.loadingImage
+
+    $('#facebox').find('.b:first, .bl').each(function() {
+      preload.push(new Image())
+      preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
+    })
+
+    $('#facebox .close').click($.facebox.close)
+    $('#facebox .close_image').attr('src', $.facebox.settings.closeImage)
+  }
+
+  // getPageScroll() by quirksmode.com
+  function getPageScroll() {
+    var xScroll, yScroll;
+    if (self.pageYOffset) {
+      yScroll = self.pageYOffset;
+      xScroll = self.pageXOffset;
+    } else if (document.documentElement && document.documentElement.scrollTop) {        // Explorer 6 Strict
+      yScroll = document.documentElement.scrollTop;
+      xScroll = document.documentElement.scrollLeft;
+    } else if (document.body) {// all other Explorers
+      yScroll = document.body.scrollTop;
+      xScroll = document.body.scrollLeft;
+    }
+    return new Array(xScroll,yScroll)
+  }
+
+  // Adapted from getPageSize() by quirksmode.com
+  function getPageHeight() {
+    var windowHeight
+    if (self.innerHeight) {    // all except Explorer
+      windowHeight = self.innerHeight;
+    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
+      windowHeight = document.documentElement.clientHeight;
+    } else if (document.body) { // other Explorers
+      windowHeight = document.body.clientHeight;
+    }
+    return windowHeight
+  }
+
+  // Backwards compatibility
+  function makeCompatible() {
+    var $s = $.facebox.settings
+
+    $s.loadingImage = $s.loading_image || $s.loadingImage
+    $s.closeImage = $s.close_image || $s.closeImage
+    $s.imageTypes = $s.image_types || $s.imageTypes
+    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml
+  }
+
+  // Figures out what you want to display and displays it
+  // formats are:
+  //     div: #id
+  //   image: blah.extension
+  //    ajax: anything else
+  function fillFaceboxFromHref(href, klass) {
+    // div
+    if (href.match(/#/)) {
+      var url    = window.location.href.split('#')[0]
+      var target = href.replace(url,'')
+      if (target == '#') return
+      $.facebox.reveal($(target).html(), klass)
+
+    // image
+    } else if (href.match($.facebox.settings.imageTypesRegexp)) {
+      fillFaceboxFromImage(href, klass)
+    // ajax
+    } else {
+      fillFaceboxFromAjax(href, klass)
+    }
+  }
+
+  function fillFaceboxFromImage(href, klass) {
+    var image = new Image()
+    image.onload = function() {
+      $.facebox.reveal('<div class="image"><img src="' + image.src + '" /></div>', klass)
+    }
+    image.src = href
+  }
+
+  function fillFaceboxFromAjax(href, klass) {
+    $.get(href, function(data) { $.facebox.reveal(data, klass) })
+  }
+
+  function skipOverlay() {
+    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null
+  }
+
+  function showOverlay() {
+    if (skipOverlay()) return
+
+    if ($('#facebox_overlay').length == 0)
+      $("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')
+
+    $('#facebox_overlay').hide().addClass("facebox_overlayBG")
+      .css('opacity', $.facebox.settings.opacity)
+      .click(function() { $(document).trigger('close.facebox') })
+      .fadeIn(200)
+    return false
+  }
+
+  function hideOverlay() {
+    if (skipOverlay()) return
+
+    $('#facebox_overlay').fadeOut(200, function(){
+      $("#facebox_overlay").removeClass("facebox_overlayBG")
+      $("#facebox_overlay").addClass("facebox_hide")
+      $("#facebox_overlay").remove()
+    })
+
+    return false
+  }
+
+  /*
+   * Bindings
+   */
+
+  $(document).bind('close.facebox', function() {
+    $(document).unbind('keydown.facebox')
+    $('#facebox').fadeOut(function() {
+      $('#facebox .content').removeClass().addClass('content')
+      $('#facebox .loading').remove()
+      $(document).trigger('afterClose.facebox')
+    })
+    hideOverlay()
+  })
+
+})(jQuery);
index 35b1d81..38f80b7 100644 (file)
@@ -110,7 +110,7 @@ function startJalview(aligURL,title,alwvar) {
 </SCRIPT>
   <form name="Form1">
 <applet name="JalviewLite"  code="jalview.bin.JalviewLite"
-archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar" width="0" height="0">
+archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar" width="0" height="0">
 <param name="debug" value="true"/>
 <param name="showbutton" value="false"/>
 </applet>
index 5890515..8ddfd2f 100644 (file)
@@ -38,7 +38,7 @@
 
 
 <applet
-   code="jalview.bin.JalviewLite" width="800" height="300" id="jvapp" mayscript="True" scriptable="True" archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   code="jalview.bin.JalviewLite" width="800" height="300" id="jvapp" mayscript="True" scriptable="True" archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="oninit" value="lJvApp"/>
 <param name="automaticScrolling" value="true"/>
 <param name="file" value="plantfdx.fa"/>
@@ -61,7 +61,7 @@
 
 
 <applet
-   code="jalview.bin.JalviewLite" width="800" height="300" id="jvfollower" mayscript="True" scriptable="True" archive="jalviewApplet.jar,JmolApplet-14.2.14_2015.06.11.jar,java-json.jar,json_simple-1.1.jar">
+   code="jalview.bin.JalviewLite" width="800" height="300" id="jvfollower" mayscript="True" scriptable="True" archive="jalviewApplet.jar,JmolApplet-14.6.4_2016.10.26.jar,java-json.jar,json_simple-1.1.jar">
 <param name="oninit" value="lJvFollow"/>
 <param name="file" value="plantfdx.fa"/>
 <param name="annotations" value="plantfdx.annotations"/>
index 407899e..e034fc2 100755 (executable)
@@ -22,7 +22,7 @@
    <mapID target="home" url="html/index.html" />
    
    <mapID target="new" url="html/whatsNew.html"/>
-   <mapID target="release" url="html/releases.html#Jalview.2.10.0b1"/>
+   <mapID target="release" url="html/releases.html#Jalview.2.10.1"/>
    <mapID target="alannotation" url="html/features/annotation.html"/>
    <mapID target="keys" url="html/keys.html"/>
    <mapID target="newkeys" url="html/features/newkeystrokes.html"/>
index bf1710c..3a6b0b3 100755 (executable)
@@ -23,9 +23,6 @@
 <!-- DO NOT WRAP THESE LINES - help2Website relies on each item being on one line! -->
        <tocitem text="Jalview Documentation" target="home" expand="true">
                        <tocitem text="What's new" target="new" expand="true">
-                               <tocitem text="Retrieval from ENSEMBL" target="ensemblfetch" />
-                               <tocitem text="UniProt Free Text Search" target="uniprotfetcher" />
-                               <tocitem text="SIFTS for mapping PDB structures to UniProt" target="siftsmapping" />
                                <tocitem text="Latest Release Notes" target="release"/>
                </tocitem>
                
index ad47dae..8adacc9 100755 (executable)
@@ -35,11 +35,10 @@ td {
     <strong>Colouring above a percentage identity threshold</strong>
   </p>
   <p>Selecting this option causes the colour scheme to be applied to
-    only those residues that occur in that column more than a certain
+    only those residues that occur in that column at least a certain
     percentage of the time. For instance, selecting the threshold to be
-    100 will only colour those columns with 100% identity.</p>
-   <p>To be coloured, a residue must match the consensus (most commonly occurring) residue for the column (or joint equal consensus).</p>
+    100 will only colour those columns with 100% identity, and selecting 50 will shade residues appearing in least 50% of the rows (or sequences) in each column.</p>
    <p>The percentage calculation may include or exclude gaps in the column, depending on the option selected for the <a href="../calculations/consensus.html">consensus calculation</a>.</p>
-   <p>With a threshold of 0, colouring is unchanged (including non-consensus residues).</p>
+   <p>With a threshold of 0, colouring is unchanged.</p>
 </body>
 </html>
index 1b0b9c1..5ae00af 100644 (file)
     number and chain code ([RES]Num:Chain). Moving the mouse over an
     associated residue in an alignment window highlights the associated
     atoms in the displayed structures. When residues are selected in the
-    Chimera window, they are highlighted on the alignment. For
-    comprehensive details of Chimera's commands, refer to the tool's
-    Help menu.
+    Chimera window, they are highlighted on the alignment.
+  <p>For comprehensive details of Chimera's commands, refer to the
+    tool's Help menu.</p>
+  <p>
+    <strong>Selecting residues in Jalview from Chimera</strong><br />
+    When a selection is highlighted in a Jalview window, use the
+    <em>Select&#8594;Select Highlighted Region</em> or press <em>B</em>
+    to add the mapped positions to the alignment window's column
+    selection.<br /> <em>Hint: Use your machine's 'switch
+      application' key combination (Alt-Tab on Windows and Linux,
+      Cmd-Tab on OSX) to quickly switch between UCSF Chimera and Jalview
+      before pressing 'B' to select highlighted regions.</em>
+  </p>
   <p>
     Basic screen operations (see <a
       href="http://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/mouse.html">Chimera
index 4b4aab9..e065494 100644 (file)
       <td><div align="left">Create Scalable Vector Graphics
           file FILE from alignment.</div></td>
     </tr>
+    <tr>
+      <td><div align="center">-biojsMSA FILE</div></td>
+      <td><div align="left">Write an HTML page to display
+          the alignment with the <a href="biojsmsa.html">
+          BioJS MSAviewer MSA</a>
+          </div>
+      </td>
+    </tr>
   </table>
 </body>
 </html>
index 2f10196..0cd6168 100644 (file)
       based structure superposition was added in Jalview 2.6</em>
   </p>
   <p>
-    <strong>Controls</strong><br> The structure is by default
-    rendered as a ribbon diagram. Moving the mouse over the structure
-    brings up tooltips giving the residue name, PDB residue number and
-    chain code, atom name and number
-    ([RES]Num:Chain.AtomName#AtomNumber). If a mapping exists to a
-    residue in any associated sequences, then this will be highlighted
-    in each one's alignment window. The converse also occurs - moving
-    the mouse over an associated residue in an alignment window
-    highlights the associated atoms in the displayed structures.
+    <strong>Controls</strong><br> The structure is by default rendered
+    as a ribbon diagram. Moving the mouse over the structure brings up
+    tooltips giving the residue name, PDB residue number and chain code,
+    atom name and number ([RES]Num:Chain.AtomName#AtomNumber). If a
+    mapping exists to a residue in any associated sequences, then this
+    will be highlighted in each one's alignment window. The converse
+    also occurs - moving the mouse over an associated residue in an
+    alignment window highlights the associated atoms in the displayed
+    structures. Press B or use
+    <em>Select&#8594;Select Highlighted columns</em> from any linked
+    alignment window to mark the columns highlighted after mousing over
+    the structure.
   </p>
   <p>Selecting a residue highlights its associated sequence residue
     and alpha carbon location. Double clicking an atom allows distances
index 796d623..69f3315 100755 (executable)
@@ -65,6 +65,19 @@ td {
     Settings&quot; under the &quot;View&quot; menu to change the
     visibility and colour of the new sequence feature.</p>
   <p>
+  <p>
+    <strong>Selecting regions from Search Results</strong>
+  </p>
+  <p>
+    Press 'B' or use the <em>Select Highlighted Columns</em> option from
+    the alignment window's select menu to add columns containing
+    highlighted search results to the alignment window's column
+    selection. Alt-'B' will add all but the highlighted columns, and
+    Ctrl (or Cmd) -B will toggle the column selection for the
+    highlighted region.
+  </p>
+  <p>
+  
     <strong>A quick Regular Expression Guide</strong>
   </p>
   <p>A regular expression is not just a simple text query - although
index ba97557..3f6a058 100644 (file)
     Much of the information retrieved by Jalview about a sequence is
     visualized on the alignment. Often, however, there are a huge number
     of ontology terms, cross-references, links to publications and other
-    kinds of data shown in the sequence ID tooltip that cannot be
-    examined. In this case, you can view and export the information
-    shown in a sequence's ID tooltip by right-clicking and selecting the
+    kinds of data associated with a sequence, and only some of these are shown in 
+    sequence ID tooltip. To show the full set of annotation and database links for
+    a sequence, right-click and select the
     <strong>&quot;<em>(sequence's name)</em></em>&rarr;Sequence
       Details ...&quot;
     </strong> entry from the <a href="../menus/popupMenu.html">pop-up menu</a>.
   </p>
   <p>
     <strong>Annotation Reports for a range of sequences</strong><br />
-    If you would like to view the tooltips for a number of sequences,
+    If you would like to view database and metadata for a number of sequences,
     simply select them all and then use the <strong>Selection&rarr;Sequence
       Details ...</strong> entry in the <a href="../menus/popupMenu.html">pop-up
       menu</a>.
index 2ba9a49..1a5fc18 100755 (executable)
@@ -167,6 +167,19 @@ columns are selected, you should use the <a href="features/hiddenRegions.html">H
       <td>Both</td>
       <td>Launches the search window</td>
     </tr>
+    <tr><td><strong>B</strong></td>
+      <td>Both</td>
+      <td>Add highlighted columns to current column selection</td>
+    </tr>
+    <tr><td><strong>Alt 'B'</strong></td>
+      <td>Both</td>
+      <td>Add all but the currently highlighted columns to current selection</td>
+    </tr>
+    <tr><td><strong>Control 'B'</strong></td>
+      <td>Both</td>
+      <td>Toggle the column selection marks for the currently highlighted 
+          columns (or all others if Alt is also pressed)</td>
+    </tr>
     <tr>
       <td><strong>H</strong></td>
       <td>Both</td>
index c8b2270..167cb25 100755 (executable)
               Columns by Annotation</a></strong> <br /> <em>Select or Hide
             columns in the alignment according to secondary structure,
             labels and values shown in alignment annotation rows. </em></li>
+        <li><strong>Select Highlighted Columns</strong> <br /> <em>Selects
+        the columns currently highlighted as a result of a find, mouse
+        over, or selection event from a linked structure viewer or other
+        application. Modifiers will work on some platforms: ALT will add
+        all but the highlighted set to the column selection, and CTRL
+        (or META) will toggle the selection. </em></li>
       </ul></li>
     <li><strong>View</strong>
       <ul>
index b93f85b..07828a3 100644 (file)
           Columns by Annotation</a></strong> <br /> <em>Select or Hide columns
         in the alignment according to secondary structure, labels and
         values shown in alignment annotation rows. </em></li>
+    <li><strong>Select Highlighted Columns</strong> <br /> <em>Selects
+        the columns currently highlighted as a result of a find, mouse
+        over, or selection event from a linked structure viewer or other
+        application. Modifiers will work on some platforms: ALT will add
+        all but the highlighted set to the column selection, and CTRL
+        (or META) will toggle the selection. </em></li>
   </ul>
 </body>
 </html>
index 3fe08cb..6f44b3d 100755 (executable)
     <tr>
       <td width="60" nowrap>
         <div align="center">
+          <strong><a name="Jalview.2.10.1">2.10.1</a><br />
+            <em>29/11/2016</em></strong>
+        </div>
+      </td>
+      <td><div align="left">
+          <em>General</em>
+          <ul>
+            <li>
+              <!-- JAL-98 -->Improved memory usage: sparse arrays used
+              for all consensus calculations
+            </li>
+            <li>
+              <!-- JAL-2177 -->Jmol updated to version 14.6.4 (released 3rd Oct 2016)
+            </li>
+            <li>Updated Jalview's Certum code signing certificate
+              for 2016-2017</li>
+          </ul>
+          <em>Application</em>
+          <ul>
+            <li>
+              <!-- JAL-1723 -->Sequence ID tool tip presents abridged
+              set of database cross-references, sorted alphabetically
+            </li>
+            <li>
+              <!-- JAL-2282-->New replacement token for creating URLs <em>just</em>
+              from database cross references. Users with custom links
+              will receive a <a href="webServices/urllinks.html#warning">warning
+                dialog</a> asking them to update their preferences.
+            </li>
+            <li>
+              <!-- JAL-2287-->Cancel button and escape listener on
+              dialog warning user about disconnecting Jalview from a
+              Chimera session
+            </li>
+            <li>
+              <!-- JAL-2320-->Jalview's Chimera control window closes if
+              the Chimera it is connected to is shut down
+            </li>
+            <li>
+              <!-- JAL-1738-->New keystroke (B) and Select highlighted
+              columns menu item to mark columns containing
+              highlighted regions (e.g. from structure selections or results
+              of a Find operation)
+            </li>
+            <li>
+              <!-- JAL-2284-->Command line option for batch-generation
+              of HTML pages rendering alignment data with the BioJS
+              MSAviewer
+            </li>
+          </ul>
+        </div></td>
+      <td>
+        <div align="left">
+          <em>General</em>
+          <ul>
+            <li>
+              <!-- JAL-2286 -->Columns with more than one modal residue
+              are not coloured or thresholded according to percent
+              identity (first observed in Jalview 2.8.2)
+            </li>
+            <li>
+              <!-- JAL-2301 -->Threonine incorrectly reported as not
+              hydrophobic
+            </li>
+            <li>
+              <!-- JAL-2318 -->Updates to documentation pages (above PID
+              threshold, amino acid properties)
+            </li>
+            <li>
+              <!-- JAL-2292 -->Lower case residues in sequences are not
+              reported as mapped to residues in a structure file in the
+              View Mapping report
+            </li>
+            <li>
+              <!--JAL-2324 -->Identical features with non-numeric scores
+              could be added multiple times to a sequence
+            </li>
+            <li>
+              <!--JAL-2323, JAL-2333,JAL-2335,JAL-2327 -->Disulphide
+              bond features shown as two highlighted residues rather
+              than a range in linked structure views, and treated
+              correctly when selecting and computing trees from features
+            </li>
+            <li>
+              <!-- JAL-2281-->Custom URL links for database
+              cross-references are matched to database name regardless
+              of case
+            </li>
+
+          </ul>
+          <em>Application</em>
+          <ul>
+            <li>
+              <!-- JAL-2282-->Custom URL links for specific database
+              names without regular expressions also offer links from
+              Sequence ID
+            </li>
+            <li>
+              <!-- JAL-2315-->Removing a single configured link in the
+              URL links pane in Connections preferences doesn't actually
+              update Jalview configuration
+            </li>
+            <li>
+              <!-- JAL-2272-->CTRL-Click on a selected region to open
+              the alignment area popup menu doesn't work on El-Capitan
+            </li>
+            <li>
+              <!-- JAL-2280 -->Jalview doesn't offer to associate mmCIF
+              files with similarly named sequences if dropped onto the
+              alignment
+            </li>
+            <li>
+              <!-- JAL-2312 -->Additional mappings are shown for PDB
+              entries where more chains exist in the PDB accession than
+              are reported in the SIFTS file
+            </li>
+            <li>
+              <!-- JAL-2317-->Certain structures do not get mapped to
+              the structure view when displayed with Chimera
+            </li>
+            <li>
+              <!-- JAL-2317-->No chains shown in the Chimera view
+              panel's View->Show Chains submenu
+            </li>
+            <li>
+              <!--JAL-2277 -->Export as HTML with embedded SVG doesn't
+              work for wrapped alignment views
+            </li>
+            <li>
+              <!--JAL-2197 -->Rename UI components for running JPred
+              predictions from 'JNet' to 'JPred'
+            </li>
+            <li>
+              <!-- JAL-2337,JAL-2277 -->Export as PNG or SVG is
+              corrupted when annotation panel vertical scroll is not at
+              first annotation row
+            </li>
+            <li>
+              <!--JAL-2332 -->Attempting to view structure for Hen
+              lysozyme results in a PDB Client error dialog box
+            </li>
+          </ul>
+<!--           <em>New Known Issues</em>
+          <ul>
+            <li></li>
+          </ul> -->
+        </div>
+      </td>
+    </tr>
+      <td width="60" nowrap>
+        <div align="center">
           <strong><a name="Jalview.2.10.0b1">2.10.0b1</a><br />
             <em>25/10/2016</em></strong>
         </div>
               <!-- JAL-1306 -->Quality and Conservation are now shown on
               load even when Consensus calculation is disabled
             </li>
+            <li>
+              <!-- JAL-1932 -->Remove right on penultimate column of 
+              alignment does nothing
+            </li>
           </ul>
           <em>Application</em>
           <ul>
               <!-- JAL-1887 -->Incorrect start and end reported for PDB
               to sequence mapping in 'View Mappings' report
             </li>
+            <li>
+              <!-- JAL-2284 -->Unable to read old Jalview projects that
+              contain non-XML data added after Jalvew wrote project.
+            </li>
+            <li><!-- JAL-2118 -->Newly created annotation row reorders
+              after clicking on it to create new annotation for a
+              column.
+            </li>
             <!--  may exclude, this is an external service stability issue  JAL-1941 
             -- > RNA 3D structure not added via DSSR service</li> -->
           </ul>
         </ul> <em>Applet</em>
         <ul>
           <li>Split frame example added to applet examples page</li>
+        </ul><em>Build and Deployment</em>
+        <ul>
+          <li><!--  JAL-1888 -->New ant target for running Jalview's test suite</li>
         </ul></td>
       <td>
         <div align="left">
index 52220d2..83c80ba 100644 (file)
 <p>
 <p>
   <strong>Discovering Database References for Sequences</strong><br>
-  Database references are associated with a sequence are displayed as a
-  list in the tooltip shown when mousing over its sequence ID. Jalview
-  uses references for the retrieval of <a
-    href="../features/viewingpdbs.html">PDB structures</a> and <a
+  Database references associated with a sequence are displayed as an
+  abbreviated list in the tooltip shown when mousing over its sequence
+  ID, and can be viewed in full via the
+  <a href="../io/exportseqreport.html">Sequence Details</a> window. .
+  Jalview also uses references for the retrieval of
+  <a href="../features/viewingpdbs.html">PDB structures</a> and <a
     href="../features/dasfeatures.html">DAS features</a>, and for
   retrieving sequence cross-references such as the protein products of a
   DNA sequence.
index 1a1f0d0..088a539 100644 (file)
     the sequence ID for the sequence (<em>since Jalview 2.10.1</em>).
   </p>
   <p>
+    <strong><a name="warning">Warning dialog about updating
+        your configured URL links</a></strong><br /> In the desktop
+    prior to Jalview 2.10.1, the only way to configure custom links for
+    a particular database cross-reference for a sequence was to give it
+    a name that
+    <em>exactly</em> matched the database source, and a regular
+    expression for filtering out any spurious matches generated when the
+    custom linked was tested against the Sequence's ID string. Since the
+    introduction of the $DB_ACCESSION$ token, however, $SEQUENCE_ID$
+    will not be used for database cross-reference accession strings, and
+    if you have custom links configured, Jalview will raise a warning
+    message so let you know that you may need to update your links to
+    use $DB_ACCESSION$.
+  </p>
+  <p>
     <strong>Regular Expression Substitution</strong><br> A url may
     contain a string of the form $SEQUENCE_ID=/<em>regular
     expression</em>/=$ or $DB_ACCESSION=/<em>regular expression</em>/=$. 
index 448430d..d1d141d 100755 (executable)
 </head>
 <body>
   <p>
-    <strong>What's new in Jalview 2.10.0b1 ?</strong>
+    <strong>What's new in Jalview 2.10.1 ?</strong>
   </p>
   <p>
-    Jalview 2.10.0b1 is a patch release for 2.10, the next major release
-    in the Jalview 2 series. Full details are in the <a
-      href="releases.html#Jalview.2.10.0b1">Jalview 2.10b1 Release
-      Notes</a>, but the highlights are below.
+    Jalview 2.10.1 was released on 29th November 2016. Full details are
+    in the <a href="releases.html#Jalview.2.10.1">Jalview 2.10.1
+      Release Notes</a>, but the highlights are below. This is also the
+    first release to include contributions from Kira Mour&atilde;o, who
+    joined Jalview's core development team in October 2016.
   </p>
   <ul>
-    <li>Drag and drop reinstated for the Jalview desktop on
-      Windows, Linux and older OSX systems.</li>
-    <li>Problems loading local PDB files have been fixed</li>
-    <li>Conservation shading can be disabled for PID and consensus
-      based colour scheme</li>
-  </ul>
-  <p><em>Major highlights of the 2.10.0 Release</em></p>
-  <ul>
-    <li><strong>Ensembl sequence fetcher</strong><br />Annotated
-      Genes, transcripts and proteins can be retrieved via Jalview's new
-      <a href="features/ensemblsequencefetcher.html">Ensembl REST
-        client</a>. Support for import of Ensembl data allows:
-      <ul>
-        <li><strong>Aligned locus view</strong><br />Transcripts
-          retrieved for a gene identifier via the Ensembl or
-          EnsemblGenomes sequence databases are automatically aligned to
-          their reference genome, and introns hidden from the view.</li>
-        <li><strong>Sequence variant data</strong><br />Jalview
-          propagates variant annotation on genomic regions onto
-          transcripts and protein products, complete with associated
-          metadata such as clinical significance.</li>
-      </ul></li>
-    <li><strong>Ensembl and ENA 'show cross-references'
-        support</strong><br />The Calculations menu's <strong>'Show
-        cross-references'</strong> now offers Ensembl as well as EMBLCDS and
-      Uniprot when CDS/Protein mapping data is available for download or
-      display. This allows variant annotation to be added directly to an
-      alignment of UniProt sequences.</li>
-    <li><strong>Working with structures</strong>
-      <ul>
-        <li><strong>More accurate structure mappings</strong><br />
-          Jalview now utilises the PDBe's SIFTS database (at EMBL-EBI)
-          to <a href="features/siftsmapping.html">match structures
-            to UniProt sequences</a>, even for structures containing
-          multiple copies of a sequence.</li>
-        <li><strong>Import structures as mmCIF</strong><br />Jalview
-          now downloads data from the EMBL-EBI's PDBe site as <a
-          href="features/mmcif.html">mmCIF</a>. This allows very large
-          structures to be imported, such as the HIV virus capsid
-          assembly.</li>
-        <li><strong>Chimera users will need to upgrade to
-            1.11.1</strong><br />If you use Chimera to view structures
-          downloaded by Jalview 2.10, you will need to make sure you are
-          running the latest version of <a href="features/chimera.html">Chimera</a>.</li>
-      </ul></li>
-    <li><strong>UniProt Free Text Search</strong><br />The new
-      search dialog for UniProt allows you to browse and retrieve
-      sequences with free-text search, or structured queries.</li>
-    <li><strong>Reference sequence alignment view</strong><br />
-      Jalview 2.9 introduced support for reference sequences. In 2.10,
-      when a reference sequence is defined for the alignment, the
-      alignment column ruler is now numbered according to the reference
-      sequence. The reference sequence for alignment views can also be
-      saved and restored from Jalview projects.</li>
+    <li><strong>More memory efficient</strong><br />We've slimmed
+      down the consensus analysis data structures used by Jalview so
+      even wider alignments can be worked with.</li>
+    <li><strong>Select highlighted region</strong><br />Press 'B'
+      or use the new menu option in the alignment window's Select menu
+      to mark columns containing highlighted regions generated from
+      structure selections, mouse-overs, or resulting from a Find
+      operation.</li>
+    <li><strong>New custom link mechanism for opening URLs
+        for database cross references.</strong><br /> If you have customised URL
+      links in your Jalview preferences, then you may already have seen
+      the <a href="#warning"> warning dialog (see below).</a></li>
+    <li><strong>New command line export option for BioJS
+        MSAviewer</strong><br />A number of small bugs with the HTML export
+      functions from the Jalview desktop were also fixed.</li>
+    <li><strong>Small but significant changes to the
+        physicochemical properties and consensus calculations</strong><br />Threonine
+      is no longer considered a non-hydrophobic residue in the protein
+      conservation calculation, and minor bugs addressed in PID and
+      consensus colouring.</li>
+    <li><strong>Correct display of disulphide bond
+        features</strong><br /> In linked structure views, Jalview would
+      highlight all residues between in addition to the two linked
+      cysteines. The 'select columns by feature' function in the feature
+      settings would also select all intermediate columns.
   </ul>
 
+  <p>
+    <strong><a name="warning">Warning dialog about updating
+        your configured URL links</a></strong><br /> In the desktop prior to Jalview
+    2.10.1, the only way to configure custom links for a particular
+    database cross-reference for a sequence was to give it a name that <em>exactly</em>
+    matched the database source, and a regular expression for filtering
+    out any spurious matches generated when the custom linked was tested
+    against the Sequence's ID string. Since the introduction of the
+    $DB_ACCESSION$ token, however, $SEQUENCE_ID$ will not be used for
+    database cross-reference accession strings, and if you have custom
+    links configured, Jalview will raise a warning message so let you
+    know that you may need to update your links to use $DB_ACCESSION$.
+  </p>
 </body>
 </html>
diff --git a/lib/Jmol-14.2.14_2015.06.11.jar b/lib/Jmol-14.2.14_2015.06.11.jar
deleted file mode 100644 (file)
index 1470745..0000000
Binary files a/lib/Jmol-14.2.14_2015.06.11.jar and /dev/null differ
diff --git a/lib/Jmol-14.6.4_2016.10.26.jar b/lib/Jmol-14.6.4_2016.10.26.jar
new file mode 100644 (file)
index 0000000..1016c3f
Binary files /dev/null and b/lib/Jmol-14.6.4_2016.10.26.jar differ
index ac1a2e3..b569f55 100644 (file)
@@ -59,8 +59,8 @@ file.reference.jalview-src=src
 file.reference.jaxrpc.jar=lib/jaxrpc.jar
 file.reference.JGoogleAnalytics_0.3.jar=lib/JGoogleAnalytics_0.3.jar
 file.reference.jhall.jar=lib/jhall.jar
-file.reference.Jmol-14.2.14_2015.06.11.jar=lib/Jmol-14.2.14_2015.06.11.jar
-file.reference.JmolApplet-14.2.14_2015.06.11.jar=appletlib/JmolApplet-14.2.14_2015.06.11.jar
+file.reference.Jmol-14.6.4_2016.10.26.jar=lib/Jmol-14.6.4_2016.10.26.jar
+file.reference.JmolApplet-14.6.4_2016.10.26.jar=appletlib/JmolApplet-14.6.4_2016.10.26.jar
 file.reference.log4j-1.2.8.jar=lib/log4j-1.2.8.jar
 file.reference.mail.jar=lib/mail.jar
 file.reference.min-jaba-client.jar=lib/min-jaba-client-2.0.jar
@@ -92,7 +92,7 @@ javac.classpath=\
     ${file.reference.jaxrpc.jar}:\
     ${file.reference.JGoogleAnalytics_0.3.jar}:\
     ${file.reference.jhall.jar}:\
-    ${file.reference.Jmol-14.2.14_2015.06.11.jar}:\
+    ${file.reference.Jmol-14.6.4_2016.10.26.jar}:\
     ${file.reference.miglayout-4.0-swing.jar}:\
     ${file.reference.log4j-1.2.8.jar}:\
     ${file.reference.mail.jar}:\
@@ -101,7 +101,7 @@ javac.classpath=\
     ${file.reference.xml-apis.jar}:\
     ${file.reference.xercesImpl.jar}:\
     ${file.reference.wsdl4j.jar}:\
-    ${file.reference.JmolApplet-14.2.14_2015.06.11.jar} \
+    ${file.reference.JmolApplet-14.6.4_2016.10.26.jar} \
     ${file.reference.varna-3.9-dev.jar}
 # Space-separated list of extra javac options
 javac.compilerargs=
index bcb07cf..3488ac6 100644 (file)
@@ -1,4 +1,4 @@
 YEAR=2016
-AUTHORS=J Procter, M Carstairs, TC Ofoegbu, AM Waterhouse, J Engelhardt, LM Lui, A Menard, D Barton, N Sherstnev, D Roldan-Martinez, M Clamp, S Searle, G Barton
-AUTHORFNAMES=Jim Procter, Mungo Carstairs, Tochukwu 'Charles' Ofoegbu, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Anne Menard, Daniel Barton, Natasha Sherstnev, David Roldan-Martinez, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton
+AUTHORS=J Procter, M Carstairs, TC Ofoegbu, K Mourao, AM Waterhouse, J Engelhardt, LM Lui, A Menard, D Barton, N Sherstnev, D Roldan-Martinez, M Clamp, S Searle, G Barton
+AUTHORFNAMES=Jim Procter, Mungo Carstairs, Tochukwu 'Charles' Ofoegbu, Kira Mourao, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Anne Menard, Daniel Barton, Natasha Sherstnev, David Roldan-Martinez, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton
  
\ No newline at end of file
index 49a0456..6360dc7 100644 (file)
@@ -125,6 +125,8 @@ action.change_font_tree_panel = Change Font (Tree Panel)
 action.colour = Colour
 action.calculate = Calculate
 action.select_all = Select all
+action.select_highlighted_columns = Select Highlighted Columns
+tooltip.select_highlighted_columns = Press B to mark highlighted columns, Ctrl-(or Cmd)-B to toggle, and Alt-B to mark all but highlighted columns 
 action.deselect_all = Deselect all
 action.invert_selection = Invert selection
 action.using_jmol = Using Jmol
@@ -1272,3 +1274,4 @@ label.SEQUENCE_ID_no_longer_used = $SEQUENCE_ID$ is no longer used for DB access
 label.SEQUENCE_ID_for_DB_ACCESSION1 = Please review your URL links in the 'Connections' tab of the Preferences window:
 label.SEQUENCE_ID_for_DB_ACCESSION2 = URL links using '$SEQUENCE_ID$' for DB accessions now use '$DB_ACCESSION$'.
 label.do_not_display_again = Do not display this message again
+label.output_seq_details = Output Sequence Details to list all database references
index 50bfd24..e5b5e27 100644 (file)
@@ -122,6 +122,8 @@ action.change_font_tree_panel = Cambiar fuente (panel del 
 action.colour = Color
 action.calculate = Calcular
 action.select_all = Seleccionar Todo
+action.select_highlighted_columns = Seleccionar columnas resaltadas
+tooltip.select_highlighted_columns = Presione B para marcar las columnas resaltadas, Ctrl (o Cmd)-B para cambiarlas, y Alt-B para marcar todas menos las columnas resaltadas
 action.deselect_all = Deseleccionar Todo
 action.invert_selection = Invertir selección
 action.using_jmol = Usar Jmol
@@ -351,8 +353,8 @@ label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation =
 label.translation_failed = Translation Failed
 label.error_when_translating_sequences_submit_bug_report = Desafortunadamente, algo fue mal a la hora de traducir tus secuencias.\nPor favor, revisa la consola Jalview java \ny presenta un informe de error que incluya el seguimiento.
 label.implementation_error  = Error de implementación:
-label.automatically_associate_structure_files_with_sequences_same_name = Quieres asociar automáticamente los {0} ficheros structure con las secuencias del alineamiento que tengan el mismo nombre?
-label.automatically_associate_structure_files_by_name = Asociar los ficheros structure por nombre automáticamente
+label.automatically_associate_structure_files_with_sequences_same_name = Quieres asociar automáticamente los {0} ficheros estructura con las secuencias del alineamiento que tengan el mismo nombre?
+label.automatically_associate_structure_files_by_name = Asociar los ficheros estructura por nombre automáticamente
 label.ignore_unmatched_dropped_files_info = Quieres <em>ignorar</em> los {0} ficheros cuyos nombres no coincidan con ningún IDs de las secuencias ?
 label.ignore_unmatched_dropped_files = Ignorar los ficheros sin coincidencias?
 label.enter_view_name = Introduzca un nombre para la vista
@@ -1272,4 +1274,5 @@ label.operation_failed = Operaci
 label.SEQUENCE_ID_no_longer_used = $SEQUENCE_ID$ no se utiliza más para accesiones DB
 label.SEQUENCE_ID_for_DB_ACCESSION1 = Por favor, revise sus URLs en la pestaña 'Conexiones' de la ventana de Preferencias:
 label.SEQUENCE_ID_for_DB_ACCESSION2 = URL enlaza usando '$SEQUENCE_ID$' para accesiones DB ahora usar '$DB_ACCESSION$'.
-label.do_not_display_again = No mostrar este mensaje de nuevo
\ No newline at end of file
+label.do_not_display_again = No mostrar este mensaje de nuevo
+label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
index 95221d2..1d57a31 100644 (file)
@@ -1,3 +1,35 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 package ext.edu.ucsf.rbvi.strucviz2;
 
 import java.awt.Color;
index 1f9ec64..439d479 100644 (file)
@@ -1,3 +1,35 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 package ext.edu.ucsf.rbvi.strucviz2;
 
 import jalview.ws.HttpClientUtils;
index 7da7a48..d2f4b11 100644 (file)
@@ -1,3 +1,35 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 package ext.edu.ucsf.rbvi.strucviz2;
 
 import java.awt.Color;
index 6fd6340..effe556 100644 (file)
@@ -1,3 +1,35 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 package ext.edu.ucsf.rbvi.strucviz2;
 
 import jalview.bin.Cache;
index 08a6cb7..77c1883 100644 (file)
@@ -1,3 +1,35 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 package ext.edu.ucsf.rbvi.strucviz2;
 
 /**
index 2b2ce48..379097c 100644 (file)
@@ -1,3 +1,35 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 package ext.edu.ucsf.rbvi.strucviz2.port;
 
 import java.io.BufferedReader;
index 6bdffe1..17874e6 100755 (executable)
@@ -26,9 +26,11 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.Profile;
 import jalview.datamodel.ProfileI;
+import jalview.datamodel.Profiles;
+import jalview.datamodel.ProfilesI;
 import jalview.datamodel.ResidueCount;
-import jalview.datamodel.SequenceI;
 import jalview.datamodel.ResidueCount.SymbolCounts;
+import jalview.datamodel.SequenceI;
 import jalview.ext.android.SparseIntArray;
 import jalview.util.Comparison;
 import jalview.util.Format;
@@ -65,13 +67,13 @@ public class AAFrequency
     }
   }
 
-  public static final ProfileI[] calculate(List<SequenceI> list,
+  public static final ProfilesI calculate(List<SequenceI> list,
           int start, int end)
   {
     return calculate(list, start, end, false);
   }
 
-  public static final ProfileI[] calculate(List<SequenceI> sequences,
+  public static final ProfilesI calculate(List<SequenceI> sequences,
           int start, int end, boolean profile)
   {
     SequenceI[] seqs = new SequenceI[sequences.size()];
@@ -81,20 +83,19 @@ public class AAFrequency
       for (int i = 0; i < sequences.size(); i++)
       {
         seqs[i] = sequences.get(i);
-        if (seqs[i].getLength() > width)
+        int length = seqs[i].getLength();
+        if (length > width)
         {
-          width = seqs[i].getLength();
+          width = length;
         }
       }
 
-      ProfileI[] reply = new ProfileI[width];
-
       if (end >= width)
       {
         end = width;
       }
 
-      calculate(seqs, start, end, reply, profile);
+      ProfilesI reply = calculate(seqs, width, start, end, profile);
       return reply;
     }
   }
@@ -103,17 +104,17 @@ public class AAFrequency
    * Calculate the consensus symbol(s) for each column in the given range.
    * 
    * @param sequences
+   * @param width
+   *          the full width of the alignment
    * @param start
    *          start column (inclusive, base zero)
    * @param end
    *          end column (exclusive)
-   * @param result
-   *          array in which to store profile per column
    * @param saveFullProfile
    *          if true, store all symbol counts
    */
-  public static final void calculate(final SequenceI[] sequences,
-          int start, int end, ProfileI[] result, boolean saveFullProfile)
+  public static final ProfilesI calculate(final SequenceI[] sequences,
+          int width, int start, int end, boolean saveFullProfile)
   {
     // long now = System.currentTimeMillis();
     int seqCount = sequences.length;
@@ -121,6 +122,8 @@ public class AAFrequency
     int nucleotideCount = 0;
     int peptideCount = 0;
 
+    ProfileI[] result = new ProfileI[width];
+
     for (int column = start; column < end; column++)
     {
       /*
@@ -183,6 +186,7 @@ public class AAFrequency
 
       result[column] = profile;
     }
+    return new Profiles(result);
     // long elapsed = System.currentTimeMillis() - now;
     // System.out.println(elapsed);
   }
@@ -221,10 +225,10 @@ public class AAFrequency
    *          the annotation row to add annotations to
    * @param profiles
    *          the source consensus data
-   * @param iStart
-   *          start column
-   * @param width
-   *          end column
+   * @param startCol
+   *          start column (inclusive)
+   * @param endCol
+   *          end column (exclusive)
    * @param ignoreGaps
    *          if true, normalise residue percentages ignoring gaps
    * @param showSequenceLogo
@@ -234,12 +238,12 @@ public class AAFrequency
    *          number of sequences
    */
   public static void completeConsensus(AlignmentAnnotation consensus,
-          ProfileI[] profiles, int iStart, int width, boolean ignoreGaps,
+          ProfilesI profiles, int startCol, int endCol, boolean ignoreGaps,
           boolean showSequenceLogo, long nseq)
   {
     // long now = System.currentTimeMillis();
     if (consensus == null || consensus.annotations == null
-            || consensus.annotations.length < width)
+            || consensus.annotations.length < endCol)
     {
       /*
        * called with a bad alignment annotation row 
@@ -248,21 +252,21 @@ public class AAFrequency
       return;
     }
 
-    final int dp = getPercentageDp(nseq);
-
-    for (int i = iStart; i < width; i++)
+    for (int i = startCol; i < endCol; i++)
     {
-      ProfileI profile;
-      if (i >= profiles.length || ((profile = profiles[i]) == null))
+      ProfileI profile = profiles.get(i);
+      if (profile == null)
       {
         /*
          * happens if sequences calculated over were 
          * shorter than alignment width
          */
         consensus.annotations[i] = null;
-        continue;
+        return;
       }
 
+      final int dp = getPercentageDp(nseq);
+
       float value = profile.getPercentageIdentity(ignoreGaps);
 
       String description = getTooltip(profile, value, showSequenceLogo,
@@ -277,8 +281,8 @@ public class AAFrequency
       {
         modalResidue = "+";
       }
-      consensus.annotations[i] = new Annotation(modalResidue,
-              description, ' ', value);
+      consensus.annotations[i] = new Annotation(modalResidue, description,
+              ' ', value);
     }
     // long elapsed = System.currentTimeMillis() - now;
     // System.out.println(-elapsed);
index 72097e0..25ee7d2 100644 (file)
 package jalview.analysis;
 
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
-import jalview.datamodel.Sequence;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Vector;
 
+import com.stevesoft.pat.Regex;
+
 public class Finder
 {
   /**
    * Implements the search algorithms for the Find dialog box.
    */
-  SearchResults searchResults;
+  SearchResultsI searchResults;
 
   AlignmentI alignment;
 
-  jalview.datamodel.SequenceGroup selection = null;
+  SequenceGroup selection = null;
 
-  Vector idMatch = null;
+  Vector<SequenceI> idMatch = null;
 
   boolean caseSensitive = false;
 
@@ -46,10 +53,10 @@ public class Finder
 
   boolean findAll = false;
 
-  com.stevesoft.pat.Regex regex = null;
+  Regex regex = null;
 
   /**
-   * hold's last-searched position between calles to find(false)
+   * holds last-searched position between calls to find(false)
    */
   int seqIndex = 0, resIndex = -1;
 
@@ -83,11 +90,10 @@ public class Finder
     {
       searchString = searchString.toUpperCase();
     }
-    regex = new com.stevesoft.pat.Regex(searchString);
+    regex = new Regex(searchString);
     regex.setIgnoreCase(!caseSensitive);
     searchResults = new SearchResults();
-    idMatch = new Vector();
-    Sequence seq;
+    idMatch = new Vector<SequenceI>();
     String item = null;
     boolean found = false;
     int end = alignment.getHeight();
@@ -102,10 +108,11 @@ public class Finder
         selection = null;
       }
     }
+    SearchResultMatchI lastm = null;
 
     while (!found && (seqIndex < end))
     {
-      seq = (Sequence) alignment.getSequenceAt(seqIndex);
+      SequenceI seq = alignment.getSequenceAt(seqIndex);
 
       if ((selection != null && selection.getSize() > 0)
               && !selection.getSequences(null).contains(seq))
@@ -140,7 +147,7 @@ public class Finder
         {
         }
 
-        if (regex.search(seq.getName()))
+        if (regex.search(seq.getName()) && !idMatch.contains(seq))
         {
           idMatch.addElement(seq);
           hasResults = true;
@@ -153,7 +160,8 @@ public class Finder
         }
 
         if (isIncludeDescription() && seq.getDescription() != null
-                && regex.search(seq.getDescription()))
+                && regex.search(seq.getDescription())
+                && !idMatch.contains(seq))
         {
           idMatch.addElement(seq);
           hasResults = true;
@@ -174,16 +182,16 @@ public class Finder
       }
 
       // /Shall we ignore gaps???? - JBPNote: Add Flag for forcing this or not
-      StringBuffer noGapsSB = new StringBuffer();
+      StringBuilder noGapsSB = new StringBuilder();
       int insertCount = 0;
-      Vector spaces = new Vector();
+      List<Integer> spaces = new ArrayList<Integer>();
 
       for (int j = 0; j < item.length(); j++)
       {
-        if (!jalview.util.Comparison.isGap(item.charAt(j)))
+        if (!Comparison.isGap(item.charAt(j)))
         {
           noGapsSB.append(item.charAt(j));
-          spaces.addElement(new Integer(insertCount));
+          spaces.add(Integer.valueOf(insertCount));
         }
         else
         {
@@ -192,7 +200,6 @@ public class Finder
       }
 
       String noGaps = noGapsSB.toString();
-
       for (int r = resIndex; r < noGaps.length(); r++)
       {
 
@@ -201,22 +208,22 @@ public class Finder
           resIndex = regex.matchedFrom();
 
           if ((selection != null && selection.getSize() > 0)
-                  && ((resIndex + Integer.parseInt(spaces.elementAt(
-                          resIndex).toString())) < selection.getStartRes()))
+                  && (resIndex + spaces.get(resIndex) < selection
+                          .getStartRes()))
           {
             continue;
           }
           // if invalid string used, then regex has no matched to/from
-          int sres = seq
-                  .findPosition(resIndex
-                          + Integer.parseInt(spaces.elementAt(resIndex)
-                                  .toString()));
-          int eres = seq.findPosition(regex.matchedTo()
-                  - 1
-                  + Integer.parseInt(spaces
-                          .elementAt(regex.matchedTo() - 1).toString()));
-
-          searchResults.addResult(seq, sres, eres);
+          int sres = seq.findPosition(resIndex + spaces.get(resIndex));
+          int eres = seq.findPosition(regex.matchedTo() - 1
+                  + (spaces.get(regex.matchedTo() - 1)));
+          // only add result if not contained in previous result
+          if (lastm == null
+                  || (lastm.getSequence() != seq || (!(lastm.getStart() <= sres && lastm
+                          .getEnd() >= eres))))
+          {
+            lastm = searchResults.addResult(seq, sres, eres);
+          }
           hasResults = true;
           if (!findAll)
           {
@@ -320,9 +327,12 @@ public class Finder
   }
 
   /**
-   * @return the idMatch
+   * Returns the (possibly empty) list of matching sequences (when search
+   * includes searching sequence names)
+   * 
+   * @return
    */
-  public Vector getIdMatch()
+  public Vector<SequenceI> getIdMatch()
   {
     return idMatch;
   }
@@ -338,7 +348,7 @@ public class Finder
   /**
    * @return the searchResults
    */
-  public SearchResults getSearchResults()
+  public SearchResultsI getSearchResults()
   {
     return searchResults;
   }
index 26966ba..8ed2c95 100644 (file)
@@ -97,4 +97,16 @@ public interface AlignViewControllerI
   public boolean parseFeaturesFile(String file, String protocol,
           boolean relaxedIdMatching);
 
+  /**
+   * mark columns containing highlighted regions (e.g. from search, structure
+   * highlight, or a mouse over event in another viewer)
+   * 
+   * @param invert
+   * @param extendCurrent
+   * @param toggle
+   * @return
+   */
+  boolean markHighlightedColumns(boolean invert, boolean extendCurrent,
+          boolean toggle);
+
 }
index e30a052..72542b3 100644 (file)
@@ -26,7 +26,8 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.CigarArray;
 import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -82,7 +83,7 @@ public interface AlignViewportI extends ViewStyleI
 
   ColumnSelection getColumnSelection();
 
-  ProfileI[] getSequenceConsensusHash();
+  ProfilesI getSequenceConsensusHash();
 
   /**
    * Get consensus data table for the cDNA complement of this alignment (if any)
@@ -145,7 +146,7 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @param hconsensus
    */
-  void setSequenceConsensusHash(ProfileI[] hconsensus);
+  void setSequenceConsensusHash(ProfilesI hconsensus);
 
   /**
    * Set the cDNA complement consensus for the viewport
@@ -423,4 +424,25 @@ public interface AlignViewportI extends ViewStyleI
    * @return true if group is defined on the alignment
    */
   boolean isSelectionDefinedGroup();
+
+  /**
+   * 
+   * @return true if there are search results on the view
+   */
+  boolean hasSearchResults();
+
+  /**
+   * set the search results for the view
+   * 
+   * @param results
+   *          - or null to clear current results
+   */
+  void setSearchResults(SearchResultsI results);
+
+  /**
+   * get search results for this view (if any)
+   * 
+   * @return search results or null
+   */
+  SearchResultsI getSearchResults();
 }
index dbc9880..f54231e 100644 (file)
@@ -132,7 +132,8 @@ public interface FeatureRenderer
   void setGroupVisibility(String group, boolean visible);
 
   /**
-   * locate features at a particular position on the given sequence
+   * Returns features at the specified position on the given sequence.
+   * Non-positional features are not included.
    * 
    * @param sequence
    * @param res
index 45e39cc..0c80c37 100644 (file)
@@ -802,7 +802,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, ap.alignFrame);
 
-    StringBuffer contents = new StringBuffer();
+    StringBuilder contents = new StringBuilder(128);
     for (SequenceI seq : sequences)
     {
       contents.append(MessageManager.formatMessage(
@@ -813,7 +813,6 @@ public class APopupMenu extends java.awt.PopupMenu implements
               seq,
               true,
               true,
-              false,
               (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr
                       .getMinMax() : null);
       contents.append("</p>");
@@ -844,9 +843,10 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
   void addPDB()
   {
-    if (seq.getAllPDBEntries() != null)
+    Vector<PDBEntry> pdbs = seq.getAllPDBEntries();
+    if (pdbs != null&& !pdbs.isEmpty())
     {
-      PDBEntry entry = seq.getAllPDBEntries().firstElement();
+      PDBEntry entry = pdbs.firstElement();
 
       if (ap.av.applet.jmolAvailable)
       {
index e5178cb..4bd77b6 100644 (file)
@@ -28,6 +28,7 @@ import jalview.commands.CommandI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -433,7 +434,7 @@ public class AlignViewport extends AlignmentViewport implements
      * there is no complement, or it is not following highlights, or no mapping
      * is found, the result will be empty.
      */
-    SearchResults sr = new SearchResults();
+    SearchResultsI sr = new SearchResults();
     int seqOffset = findComplementScrollTarget(sr);
     if (!sr.isEmpty())
     {
index 813ab84..e97c347 100644 (file)
@@ -25,7 +25,7 @@ import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.bin.JalviewLite;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceI;
 import jalview.structure.StructureSelectionManager;
 
@@ -293,7 +293,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    * Highlight the given results on the alignment.
    * 
    */
-  public void highlightSearchResults(SearchResults results)
+  public void highlightSearchResults(SearchResultsI results)
   {
     scrollToPosition(results);
     seqPanel.seqCanvas.highlightSearchResults(results);
@@ -306,7 +306,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    * @param results
    * @return false if results were not found
    */
-  public boolean scrollToPosition(SearchResults results)
+  public boolean scrollToPosition(SearchResultsI results)
   {
     return scrollToPosition(results, true);
   }
@@ -320,10 +320,10 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    *          - when set, the overview will be recalculated (takes longer)
    * @return false if results were not found
    */
-  public boolean scrollToPosition(SearchResults results,
+  public boolean scrollToPosition(SearchResultsI results,
           boolean redrawOverview)
   {
-    return scrollToPosition(results, redrawOverview, false);
+    return scrollToPosition(results, 0, redrawOverview, false);
   }
 
   /**
@@ -335,7 +335,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    *          - when set, the overview will be recalculated (takes longer)
    * @return false if results were not found
    */
-  public boolean scrollToPosition(SearchResults results,
+  public boolean scrollToPosition(SearchResultsI results,
+          int verticalOffset,
           boolean redrawOverview, boolean centre)
   {
     // do we need to scroll the panel?
@@ -347,6 +348,10 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
       {
         return false;
       }
+      /*
+       * allow for offset of target sequence (actually scroll to one above it)
+       */
+
       SequenceI seq = alignment.getSequenceAt(seqIndex);
       int[] r = results.getResults(seq, 0, alignment.getWidth());
       if (r == null)
@@ -391,6 +396,11 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
       {
         return false;
       }
+
+      /*
+       * allow for offset of target sequence (actually scroll to one above it)
+       */
+      seqIndex = Math.max(0, seqIndex - verticalOffset);
       return scrollTo(start, end, seqIndex, false, redrawOverview);
     }
     return true;
@@ -419,6 +429,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
     {
       start = ostart;
     }
+
     if (!av.getWrapAlignment())
     {
       /*
@@ -902,14 +913,14 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    * @param seqOffset
    *          the number of visible sequences to show above the mapped region
    */
-  protected void scrollToCentre(SearchResults sr, int seqOffset)
+  protected void scrollToCentre(SearchResultsI sr, int seqOffset)
   {
     /*
      * To avoid jumpy vertical scrolling (if some sequences are gapped or not
      * mapped), we can make the scroll-to location a sequence above the one
      * actually mapped.
      */
-    SequenceI mappedTo = sr.getResultSequence(0);
+    SequenceI mappedTo = sr.getResults().get(0).getSequence();
     List<SequenceI> seqs = av.getAlignment().getSequences();
 
     /*
@@ -931,16 +942,14 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
     {
       return; // failsafe, shouldn't happen
     }
-    sequenceIndex = Math.max(0, sequenceIndex - seqOffset);
-    sr.getResults().get(0)
-            .setSequence(av.getAlignment().getSequenceAt(sequenceIndex));
 
     /*
      * Scroll to position but centring the target residue. Also set a state flag
      * to prevent adjustmentValueChanged performing this recursively.
      */
     setFollowingComplementScroll(true);
-    scrollToPosition(sr, true, true);
+    // this should be scrollToPosition(sr,verticalOffset,
+    scrollToPosition(sr, seqOffset, true, true);
   }
 
   private void sendViewPosition()
index b925284..133cc94 100644 (file)
@@ -180,7 +180,7 @@ public class AppletJmol extends EmbmenuFrame implements
     this.ap = ap;
     jmb = new AppletJmolBinding(this, ap.getStructureSelectionManager(),
             new PDBEntry[] { pdbentry }, new SequenceI[][] { seq },
-            new String[][] { chains }, protocol);
+            protocol);
     jmb.setColourBySequence(true);
     if (pdbentry.getId() == null || pdbentry.getId().length() < 1)
     {
@@ -369,7 +369,7 @@ public class AppletJmol extends EmbmenuFrame implements
     jmb.loadInline(string);
   }
 
-  void setChainMenuItems(Vector<String> chains)
+  void setChainMenuItems(List<String> chains)
   {
     chainMenu.removeAll();
 
@@ -588,7 +588,7 @@ public class AppletJmol extends EmbmenuFrame implements
       repaint();
       return;
     }
-    setChainMenuItems(jmb.chainNames);
+    setChainMenuItems(jmb.getChainNames());
     jmb.colourBySequence(ap);
 
     setTitle(jmb.getViewerTitle());
index 6ec5b4d..684d357 100644 (file)
@@ -29,8 +29,6 @@ import jalview.structure.StructureSelectionManager;
 import java.awt.Container;
 import java.util.Map;
 
-import javajs.awt.Dimension;
-
 import org.jmol.api.JmolAppConsoleInterface;
 import org.jmol.console.AppletConsole;
 import org.jmol.java.BS;
@@ -45,9 +43,9 @@ class AppletJmolBinding extends JalviewJmolBinding
 
   public AppletJmolBinding(AppletJmol appletJmol,
           StructureSelectionManager sSm, PDBEntry[] pdbentry,
-          SequenceI[][] seq, String[][] chains, String protocol)
+          SequenceI[][] seq, String protocol)
   {
-    super(sSm, pdbentry, seq, chains, protocol);
+    super(sSm, pdbentry, seq, protocol);
     appletJmolBinding = appletJmol;
   }
 
@@ -113,12 +111,14 @@ class AppletJmolBinding extends JalviewJmolBinding
     appletJmolBinding.updateTitleAndMenus();
   }
 
+  @Override
   public void updateColours(Object source)
   {
     AlignmentPanel ap = (AlignmentPanel) source;
     colourBySequence(ap);
   }
 
+  @Override
   public void showUrl(String url)
   {
     try
@@ -143,6 +143,7 @@ class AppletJmolBinding extends JalviewJmolBinding
     // do nothing.
   }
 
+  @Override
   public void selectionChanged(BS arg0)
   {
     // TODO Auto-generated method stub
@@ -183,7 +184,7 @@ class AppletJmolBinding extends JalviewJmolBinding
   }
 
   @Override
-  public Dimension resizeInnerPanel(String data)
+  public int[] resizeInnerPanel(String data)
   {
     // TODO Auto-generated method stub
     return null;
index 929a871..5ffbaa4 100644 (file)
@@ -49,11 +49,11 @@ public class ExtJmol extends JalviewJmolBinding
   private AlignmentPanel ap;
 
   protected ExtJmol(jalview.appletgui.AlignFrame alframe,
-          PDBEntry[] pdbentry, SequenceI[][] seq, String[][] chains,
+          PDBEntry[] pdbentry, SequenceI[][] seq,
           String protocol)
   {
     super(alframe.alignPanel.getStructureSelectionManager(), pdbentry, seq,
-            chains, protocol);
+            protocol);
   }
 
   public ExtJmol(Viewer viewer, AlignmentPanel alignPanel,
@@ -64,6 +64,7 @@ public class ExtJmol extends JalviewJmolBinding
     notifyFileLoaded(null, null, null, null, 0);
   }
 
+  @Override
   public void updateColours(Object source)
   {
 
@@ -71,6 +72,7 @@ public class ExtJmol extends JalviewJmolBinding
 
   }
 
+  @Override
   public void showUrl(String arg0)
   {
     showUrl(arg0, "jmol");
@@ -126,6 +128,7 @@ public class ExtJmol extends JalviewJmolBinding
     // ignore
   }
 
+  @Override
   public void selectionChanged(BS arg0)
   {
     System.out.println(arg0);
index 82736d7..2fca07d 100644 (file)
@@ -22,6 +22,7 @@ package jalview.appletgui;
 
 import jalview.api.FeatureColourI;
 import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.io.FeaturesFile;
@@ -225,7 +226,7 @@ public class FeatureRenderer extends
             start.setText(features[index].getBegin() + "");
             end.setText(features[index].getEnd() + "");
 
-            SearchResults highlight = new SearchResults();
+            SearchResultsI highlight = new SearchResults();
             highlight.addResult(sequences[0], features[index].getBegin(),
                     features[index].getEnd());
 
index 75d9b9e..d2fe69c 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.appletgui;
 
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultMatchI;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.util.MessageManager;
@@ -50,7 +51,7 @@ public class Finder extends Panel implements ActionListener
 
   Frame frame;
 
-  SearchResults searchResults;
+  SearchResultsI searchResults;
 
   int seqIndex = 0;
 
@@ -76,6 +77,7 @@ public class Finder extends Panel implements ActionListener
     frame.repaint();
     frame.addWindowListener(new WindowAdapter()
     {
+      @Override
       public void windowClosing(WindowEvent evt)
       {
         ap.highlightSearchResults(null);
@@ -84,6 +86,7 @@ public class Finder extends Panel implements ActionListener
     textfield.requestFocus();
   }
 
+  @Override
   public void actionPerformed(ActionEvent evt)
   {
     if (evt.getSource() == textfield)
@@ -114,13 +117,15 @@ public class Finder extends Panel implements ActionListener
     SequenceFeature[] features = new SequenceFeature[searchResults
             .getSize()];
 
-    for (int i = 0; i < searchResults.getSize(); i++)
+    int i = 0;
+    for (SearchResultMatchI match : searchResults.getResults())
     {
-      seqs[i] = searchResults.getResultSequence(i);
+      seqs[i] = match.getSequence().getDatasetSequence();
 
       features[i] = new SequenceFeature(textfield.getText().trim(),
-              "Search Results", null, searchResults.getResultStart(i),
-              searchResults.getResultEnd(i), "Search Results");
+              "Search Results", null, match.getStart(), match.getEnd(),
+              "Search Results");
+      i++;
     }
 
     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
@@ -152,7 +157,7 @@ public class Finder extends Panel implements ActionListener
     seqIndex = finder.getSeqIndex();
     resIndex = finder.getResIndex();
     searchResults = finder.getSearchResults();
-    Vector idMatch = finder.getIdMatch();
+    Vector<SequenceI> idMatch = finder.getIdMatch();
     boolean haveResults = false;
     // set or reset the GUI
     if ((idMatch.size() > 0))
@@ -246,6 +251,7 @@ public class Finder extends Panel implements ActionListener
     textfield.setBounds(new Rectangle(40, 17, 133, 21));
     textfield.addKeyListener(new java.awt.event.KeyAdapter()
     {
+      @Override
       public void keyTyped(KeyEvent e)
       {
         textfield_keyTyped(e);
index 7216bfe..5d6bb07 100755 (executable)
@@ -21,7 +21,7 @@
 package jalview.appletgui;
 
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.ScaleRenderer;
@@ -50,8 +50,6 @@ public class SeqCanvas extends Panel
 
   AlignViewport av;
 
-  SearchResults searchResults = null;
-
   boolean fastPaint = false;
 
   int cursorX = 0;
@@ -632,9 +630,10 @@ public class SeqCanvas extends Panel
 
       // / Highlight search Results once all sequences have been drawn
       // ////////////////////////////////////////////////////////
-      if (searchResults != null)
+      if (av.hasSearchResults())
       {
-        int[] visibleResults = searchResults.getResults(nextSeq, startRes,
+        int[] visibleResults = av.getSearchResults().getResults(nextSeq,
+                startRes,
                 endRes);
         if (visibleResults != null)
         {
@@ -843,10 +842,9 @@ public class SeqCanvas extends Panel
     }
   }
 
-  public void highlightSearchResults(SearchResults results)
+  public void highlightSearchResults(SearchResultsI results)
   {
-    searchResults = results;
-
+    av.setSearchResults(results);
     repaint();
   }
 
index 6ca9499..8d6e683 100644 (file)
@@ -25,8 +25,9 @@ import jalview.commands.EditCommand;
 import jalview.commands.EditCommand.Action;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
-import jalview.datamodel.SearchResults.Match;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
@@ -458,7 +459,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
    * @param results
    * @return true if results were matched, false if not
    */
-  private boolean setStatusMessage(SearchResults results)
+  private boolean setStatusMessage(SearchResultsI results)
   {
     AlignmentI al = this.av.getAlignment();
     int sequenceIndex = al.findIndex(results);
@@ -467,7 +468,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       return false;
     }
     SequenceI ds = al.getSequenceAt(sequenceIndex).getDatasetSequence();
-    for (Match m : results.getResults())
+    for (SearchResultMatchI m : results.getResults())
     {
       SequenceI seq = m.getSequence();
       if (seq.getDatasetSequence() != null)
@@ -559,7 +560,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
       if (features != null && features.length > 0)
       {
-        SearchResults highlight = new SearchResults();
+        SearchResultsI highlight = new SearchResults();
         highlight.addResult(sequence, features[0].getBegin(),
                 features[0].getEnd());
         seqCanvas.highlightSearchResults(highlight);
@@ -731,7 +732,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   }
 
   @Override
-  public void highlightSequence(SearchResults results)
+  public void highlightSequence(SearchResultsI results)
   {
     if (av.isFollowHighlight())
     {
index 164ba27..bcb4e7b 100755 (executable)
@@ -51,6 +51,7 @@ import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.security.AllPermission;
 import java.security.CodeSource;
@@ -650,22 +651,29 @@ public class Jalview
           {
             File imageFile = new File(file);
             imageName = imageFile.getName();
-            new HtmlSvgOutput(new File(file), af.alignPanel);
+            HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
+            htmlSVG.exportHTML(file);
+
             System.out.println("Creating HTML image: " + file);
             continue;
           }
           else if (format.equalsIgnoreCase("biojsmsa"))
           {
-            BioJsHTMLOutput.updateBioJS();
+            if (file == null)
+            {
+              System.err.println("The output html file must not be null");
+              return;
+            }
             try
             {
-              Thread.sleep(1500);
-            } catch (InterruptedException e)
+              BioJsHTMLOutput
+                      .refreshVersionInfo(BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
+            } catch (URISyntaxException e)
             {
               e.printStackTrace();
             }
-            BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel, af);
-            bjs.exportJalviewAlignmentAsBioJsHtmlFile(file);
+            BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
+            bjs.exportHTML(file);
             System.out.println("Creating BioJS MSA Viwer HTML file: "
                     + file);
             continue;
index f508bc3..e9a0dbf 100644 (file)
@@ -243,10 +243,6 @@ public class AlignViewController implements AlignViewControllerI
         SequenceFeature[] sfs = sq.getSequenceFeatures();
         if (sfs != null)
         {
-          /*
-           * check whether the feature start/end (base 1) 
-           * overlaps the selection start/end
-           */
           int ist = sq.findIndex(sq.getStart());
           int iend = sq.findIndex(sq.getEnd());
           if (iend < startPosition || ist > endPosition)
@@ -264,29 +260,54 @@ public class AlignViewController implements AlignViewControllerI
               // - findIndex wastes time by starting from first character and
               // counting
 
-              int i = sq.findIndex(sf.getBegin());
-              int j = sq.findIndex(sf.getEnd());
-              if (j < startPosition || i > endPosition)
+              int sfStartCol = sq.findIndex(sf.getBegin());
+              int sfEndCol = sq.findIndex(sf.getEnd());
+
+              if (sf.isContactFeature())
+              {
+                /*
+                 * 'contact' feature - check for 'start' or 'end'
+                 * position within the selected region
+                 */
+                if (sfStartCol >= startPosition
+                        && sfStartCol <= endPosition)
+                {
+                  bs.set(sfStartCol - 1);
+                  sequenceHasFeature = true;
+                }
+                if (sfEndCol >= startPosition && sfEndCol <= endPosition)
+                {
+                  bs.set(sfEndCol - 1);
+                  sequenceHasFeature = true;
+                }
+                continue;
+              }
+
+              /*
+               * contiguous feature - select feature positions (if any) 
+               * within the selected region
+               */
+              if (sfStartCol > endPosition || sfEndCol < startPosition)
               {
                 // feature is outside selected region
                 continue;
               }
               sequenceHasFeature = true;
-              if (i < startPosition)
+              if (sfStartCol < startPosition)
               {
-                i = startPosition;
+                sfStartCol = startPosition;
               }
-              if (i < ist)
+              if (sfStartCol < ist)
               {
-                i = ist;
+                sfStartCol = ist;
               }
-              if (j > endPosition)
+              if (sfEndCol > endPosition)
               {
-                j = endPosition;
+                sfEndCol = endPosition;
               }
-              for (; i <= j; i++)
+              for (; sfStartCol <= sfEndCol; sfStartCol++)
               {
-                bs.set(i - 1); // convert to base 0
+                bs.set(sfStartCol - 1); // convert to base 0
               }
             }
           }
@@ -381,4 +402,66 @@ public class AlignViewController implements AlignViewControllerI
     return featuresFile;
 
   }
+
+  @Override
+  public boolean markHighlightedColumns(boolean invert,
+          boolean extendCurrent, boolean toggle)
+  {
+    if (!viewport.hasSearchResults())
+    {
+      // do nothing if no selection exists
+      return false;
+    }
+    // JBPNote this routine could also mark rows, not just columns.
+    BitSet bs = new BitSet();
+    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null || extendCurrent) ? viewport
+            .getAlignment() : viewport.getSelectionGroup();
+
+    // this could be a lambda... - the remains of the method is boilerplate,
+    // except for the different messages for reporting selection.
+    int nseq = viewport.getSearchResults().markColumns(sqcol, bs);
+
+    ColumnSelection cs = viewport.getColumnSelection();
+    if (cs == null)
+    {
+      cs = new ColumnSelection();
+    }
+
+    if (bs.cardinality() > 0 || invert)
+    {
+      boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
+              sqcol.getEndRes(), invert, extendCurrent, toggle);
+      if (changed)
+      {
+        viewport.setColumnSelection(cs);
+        alignPanel.paintAlignment(true);
+        int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
+                - bs.cardinality()
+                : bs.cardinality();
+        avcg.setStatus(MessageManager.formatMessage(
+                "label.view_controller_toggled_marked",
+                new String[] {
+                    toggle ? MessageManager.getString("label.toggled")
+                            : MessageManager.getString("label.marked"),
+                    String.valueOf(columnCount),
+                    invert ? MessageManager
+                            .getString("label.not_containing")
+                            : MessageManager.getString("label.containing"),
+                    "Highlight", Integer.valueOf(nseq).toString() }));
+        return true;
+      }
+    }
+    else
+    {
+      avcg.setStatus(MessageManager
+              .formatMessage("No highlighted regions marked"));
+      if (!extendCurrent)
+      {
+        cs.clear();
+        alignPanel.paintAlignment(true);
+      }
+    }
+    return false;
+  }
+
 }
index c5204eb..4fbfd62 100644 (file)
@@ -301,7 +301,7 @@ public class AlignedCodonFrame
    *          where highlighted regions go
    */
   public void markMappedRegion(SequenceI seq, int index,
-          SearchResults results)
+          SearchResultsI results)
   {
     int[] codon;
     SequenceI ds = seq.getDatasetSequence();
index 2289ac6..bd78827 100755 (executable)
@@ -661,7 +661,7 @@ public class Alignment implements AlignmentI
    * jalview.datamodel.AlignmentI#findIndex(jalview.datamodel.SearchResults)
    */
   @Override
-  public int findIndex(SearchResults results)
+  public int findIndex(SearchResultsI results)
   {
     int i = 0;
 
index 1d37fa6..7274e5f 100755 (executable)
@@ -426,7 +426,7 @@ public interface AlignmentI extends AnnotatedCollectionI
    * @param results
    * @return -1 or index of sequence in alignment
    */
-  int findIndex(SearchResults results);
+  int findIndex(SearchResultsI results);
 
   /**
    * append sequences and annotation from another alignment object to this one.
index 6a6ccd0..9c3a8e7 100755 (executable)
@@ -121,16 +121,6 @@ public class PDBEntry
   {
   }
 
-  /**
-   * Constructor given file path and PDB id.
-   * 
-   * @param filePath
-   */
-  // public PDBEntry(String filePath, String pdbId)
-  // {
-  // this.file = filePath;
-  // this.id = pdbId;
-  // }
 
   public PDBEntry(String pdbId, String chain, PDBEntry.Type type,
           String filePath)
index 5464596..1501808 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
 
index cf2b394..65a5c0d 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
 public interface ProfileI
diff --git a/src/jalview/datamodel/Profiles.java b/src/jalview/datamodel/Profiles.java
new file mode 100644 (file)
index 0000000..f65830a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+public class Profiles implements ProfilesI
+{
+
+  private ProfileI[] profiles;
+
+  public Profiles(ProfileI[] p)
+  {
+    profiles = p;
+  }
+
+  /**
+   * Returns the profile for the given column, or null if none found
+   * 
+   * @param col
+   */
+  @Override
+  public ProfileI get(int col)
+  {
+    return profiles != null && col >= 0 && col < profiles.length ? profiles[col]
+            : null;
+  }
+
+  /**
+   * Returns the first column (base 0) covered by the profiles
+   */
+  @Override
+  public int getStartColumn()
+  {
+    return 0;
+  }
+
+  /**
+   * Returns the last column (base 0) covered by the profiles
+   */
+  @Override
+  public int getEndColumn()
+  {
+    return profiles == null ? 0 : profiles.length - 1;
+  }
+
+}
diff --git a/src/jalview/datamodel/ProfilesI.java b/src/jalview/datamodel/ProfilesI.java
new file mode 100644 (file)
index 0000000..82398d9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+public interface ProfilesI
+{
+
+  ProfileI get(int i);
+
+  int getStartColumn();
+
+  int getEndColumn();
+
+}
index 0d0348c..3e3a966 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
 import jalview.util.Comparison;
diff --git a/src/jalview/datamodel/SearchResultMatchI.java b/src/jalview/datamodel/SearchResultMatchI.java
new file mode 100644 (file)
index 0000000..a47ca8b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+/**
+ * An interface that describes one matched region of an alignment, as one
+ * contiguous portion of a single dataset sequence
+ */
+public interface SearchResultMatchI
+{
+  /**
+   * Returns the matched sequence
+   * 
+   * @return
+   */
+  SequenceI getSequence();
+
+  /**
+   * Returns the start position of the match in the sequence (base 1)
+   * 
+   * @return
+   */
+  int getStart();
+
+  /**
+   * Returns the end position of the match in the sequence (base 1)
+   * 
+   * @return
+   */
+  int getEnd();
+
+}
\ No newline at end of file
index b9db461..1bf5475 100755 (executable)
 package jalview.datamodel;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.BitSet;
 import java.util.List;
 
 /**
  * Holds a list of search result matches, where each match is a contiguous
  * stretch of a single sequence.
  * 
- * @author gmcarstairs
+ * @author gmcarstairs amwaterhouse
  *
  */
-public class SearchResults
+public class SearchResults implements SearchResultsI
 {
 
-  private List<Match> matches = new ArrayList<Match>();
+  private List<SearchResultMatchI> matches = new ArrayList<SearchResultMatchI>();
 
   /**
    * One match consists of a sequence reference, start and end positions.
    * Discontiguous ranges in a sequence require two or more Match objects.
    */
-  public class Match
+  public class Match implements SearchResultMatchI
   {
     SequenceI sequence;
 
@@ -55,7 +55,10 @@ public class SearchResults
     int end;
 
     /**
-     * Constructor
+     * create a Match on a range of sequence. Match always holds region in
+     * forwards order, even if given in reverse order (such as from a mapping to
+     * a reverse strand); this avoids trouble for routines that highlight search
+     * results etc
      * 
      * @param seq
      *          a sequence
@@ -80,48 +83,54 @@ public class SearchResults
       }
       else
       {
+        // TODO: JBP could mark match as being specified in reverse direction
+        // for use
+        // by caller ? e.g. visualizing reverse strand highlight
         this.start = end;
         this.end = start;
       }
     }
 
+    /* (non-Javadoc)
+     * @see jalview.datamodel.SearchResultMatchI#getSequence()
+     */
+    @Override
     public SequenceI getSequence()
     {
       return sequence;
     }
 
+    /* (non-Javadoc)
+     * @see jalview.datamodel.SearchResultMatchI#getStart()
+     */
+    @Override
     public int getStart()
     {
       return start;
     }
 
+    /* (non-Javadoc)
+     * @see jalview.datamodel.SearchResultMatchI#getEnd()
+     */
+    @Override
     public int getEnd()
     {
       return end;
     }
 
     /**
-     * Returns the string of characters in the matched region, prefixed by the
-     * start position, e.g. "12CGT" or "208K"
+     * Returns a representation as "seqid/start-end"
      */
     @Override
     public String toString()
     {
-      final int from = Math.max(start - 1, 0);
-      String startPosition = String.valueOf(from);
-      return startPosition + getCharacters();
-    }
-
-    /**
-     * Returns the string of characters in the matched region.
-     */
-    public String getCharacters()
-    {
-      char[] chars = sequence.getSequence();
-      // convert start/end to base 0 (with bounds check)
-      final int from = Math.max(start - 1, 0);
-      final int to = Math.min(end, chars.length + 1);
-      return String.valueOf(Arrays.copyOfRange(chars, from, to));
+      StringBuilder sb = new StringBuilder();
+      if (sequence != null)
+      {
+        sb.append(sequence.getName()).append("/");
+      }
+      sb.append(start).append("-").append(end);
+      return sb.toString();
     }
 
     public void setSequence(SequenceI seq)
@@ -150,46 +159,38 @@ public class SearchResults
     @Override
     public boolean equals(Object obj)
     {
-      if (obj == null || !(obj instanceof Match))
+      if (obj == null || !(obj instanceof SearchResultMatchI))
       {
         return false;
       }
-      Match m = (Match) obj;
-      return (this.sequence == m.sequence && this.start == m.start && this.end == m.end);
+      SearchResultMatchI m = (SearchResultMatchI) obj;
+      return (sequence == m.getSequence() && start == m.getStart() && end == m
+              .getEnd());
     }
   }
 
-  /**
-   * This method replaces the old search results which merely held an alignment
-   * index of search matches. This broke when sequences were moved around the
-   * alignment
-   * 
-   * @param seq
-   *          Sequence
-   * @param start
-   *          int
-   * @param end
-   *          int
+  /* (non-Javadoc)
+   * @see jalview.datamodel.SearchResultsI#addResult(jalview.datamodel.SequenceI, int, int)
    */
-  public void addResult(SequenceI seq, int start, int end)
+  @Override
+  public SearchResultMatchI addResult(SequenceI seq, int start, int end)
   {
-    matches.add(new Match(seq, start, end));
+    Match m = new Match(seq, start, end);
+    matches.add(m);
+    return m;
   }
 
-  /**
-   * Quickly check if the given sequence is referred to in the search results
-   * 
-   * @param sequence
-   *          (specific alignment sequence or a dataset sequence)
-   * @return true if the results involve sequence
+  /* (non-Javadoc)
+   * @see jalview.datamodel.SearchResultsI#involvesSequence(jalview.datamodel.SequenceI)
    */
+  @Override
   public boolean involvesSequence(SequenceI sequence)
   {
     SequenceI ds = sequence.getDatasetSequence();
-    for (Match m : matches)
+    for (SearchResultMatchI _m : matches)
     {
-      if (m.sequence != null
-              && (m.sequence == sequence || m.sequence == ds))
+      SequenceI matched = _m.getSequence();
+      if (matched != null && (matched == sequence || matched == ds))
       {
         return true;
       }
@@ -197,11 +198,10 @@ public class SearchResults
     return false;
   }
 
-  /**
-   * This Method returns the search matches which lie between the start and end
-   * points of the sequence in question. It is optimised for returning objects
-   * for drawing on SequenceCanvas
+  /* (non-Javadoc)
+   * @see jalview.datamodel.SearchResultsI#getResults(jalview.datamodel.SequenceI, int, int)
    */
+  @Override
   public int[] getResults(SequenceI sequence, int start, int end)
   {
     if (matches.isEmpty())
@@ -213,8 +213,11 @@ public class SearchResults
     int[] tmp = null;
     int resultLength, matchStart = 0, matchEnd = 0;
     boolean mfound;
-    for (Match m : matches)
+    Match m;
+    for (SearchResultMatchI _m : matches)
     {
+      m = (Match) _m;
+
       mfound = false;
       if (m.sequence == sequence)
       {
@@ -269,97 +272,76 @@ public class SearchResults
     return result;
   }
 
-  public int getSize()
-  {
-    return matches.size();
-  }
-
-  public SequenceI getResultSequence(int index)
-  {
-    return matches.get(index).sequence;
-  }
-
-  /**
-   * Returns the start position of the i'th match in the search results.
-   * 
-   * @param i
-   * @return
-   */
-  public int getResultStart(int i)
+  @Override
+  public int markColumns(SequenceCollectionI sqcol, BitSet bs)
   {
-    return matches.get(i).start;
+    int count = 0;
+    BitSet mask = new BitSet();
+    for (SequenceI s : sqcol.getSequences())
+    {
+      int[] cols = getResults(s, sqcol.getStartRes(), sqcol.getEndRes());
+      if (cols != null)
+      {
+        for (int pair = 0; pair < cols.length; pair += 2)
+        {
+          mask.set(cols[pair], cols[pair + 1] + 1);
+        }
+      }
+    }
+    // compute columns that were newly selected
+    BitSet original = (BitSet) bs.clone();
+    original.and(mask);
+    count = mask.cardinality() - original.cardinality();
+    // and mark ranges not already marked
+    bs.or(mask);
+    return count;
   }
 
-  /**
-   * Returns the end position of the i'th match in the search results.
-   * 
-   * @param i
-   * @return
+  /* (non-Javadoc)
+   * @see jalview.datamodel.SearchResultsI#getSize()
    */
-  public int getResultEnd(int i)
+  @Override
+  public int getSize()
   {
-    return matches.get(i).end;
+    return matches.size();
   }
 
-  /**
-   * Returns true if no search result matches are held.
-   * 
-   * @return
+  /* (non-Javadoc)
+   * @see jalview.datamodel.SearchResultsI#isEmpty()
    */
+  @Override
   public boolean isEmpty()
   {
     return matches.isEmpty();
   }
 
-  /**
-   * Returns the list of matches.
-   * 
-   * @return
+  /* (non-Javadoc)
+   * @see jalview.datamodel.SearchResultsI#getResults()
    */
-  public List<Match> getResults()
+  @Override
+  public List<SearchResultMatchI> getResults()
   {
     return matches;
   }
 
   /**
-   * Return the results as a string of characters (bases) prefixed by start
-   * position(s). Meant for use when the context ensures that all matches are to
-   * regions of the same sequence (otherwise the result is meaningless).
+   * Return the results as a list of matches [seq1/from-to, seq2/from-to, ...]
    * 
    * @return
    */
   @Override
   public String toString()
   {
-    StringBuilder result = new StringBuilder(256);
-    for (Match m : matches)
-    {
-      result.append(m.toString());
-    }
-    return result.toString();
-  }
-
-  /**
-   * Return the results as a string of characters (bases). Meant for use when
-   * the context ensures that all matches are to regions of the same sequence
-   * (otherwise the result is meaningless).
-   * 
-   * @return
-   */
-  public String getCharacters()
-  {
-    StringBuilder result = new StringBuilder(256);
-    for (Match m : matches)
-    {
-      result.append(m.getCharacters());
-    }
-    return result.toString();
+    return matches == null ? "" : matches.toString();
   }
 
   /**
-   * Hashcode is has derived from the list of matches. This ensures that when
-   * two SearchResults objects satisfy the test for equals(), then they have the
+   * Hashcode is derived from the list of matches. This ensures that when two
+   * SearchResults objects satisfy the test for equals(), then they have the
    * same hashcode.
+   * 
+   * @see Match#hashCode()
+   * @see java.util.AbstractList#hashCode()
    */
   @Override
   public int hashCode()
@@ -374,11 +356,11 @@ public class SearchResults
   @Override
   public boolean equals(Object obj)
   {
-    if (obj == null || !(obj instanceof SearchResults))
+    if (obj == null || !(obj instanceof SearchResultsI))
     {
       return false;
     }
-    SearchResults sr = (SearchResults) obj;
-    return ((ArrayList<Match>) this.matches).equals(sr.matches);
+    SearchResultsI sr = (SearchResultsI) obj;
+    return matches.equals(sr.getResults());
   }
 }
diff --git a/src/jalview/datamodel/SearchResultsI.java b/src/jalview/datamodel/SearchResultsI.java
new file mode 100644 (file)
index 0000000..52a0467
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.BitSet;
+import java.util.List;
+
+/**
+ * An interface describing the result of a search or other operation which
+ * highlights matched regions of an alignment
+ */
+public interface SearchResultsI
+{
+
+  /**
+   * Adds one region to the results
+   * 
+   * @param seq
+   *          Sequence
+   * @param start
+   *          int
+   * @param end
+   *          int
+   * @return
+   */
+  SearchResultMatchI addResult(SequenceI seq, int start, int end);
+
+  /**
+   * Answers true if the search results include the given sequence (or its
+   * dataset sequence), else false
+   * 
+   * @param sequence
+   * @return
+   */
+  boolean involvesSequence(SequenceI sequence);
+
+  /**
+   * Returns an array of [from, to, from, to..] matched columns (base 0) between
+   * the given start and end columns of the given sequence. Returns null if no
+   * matches overlap the specified region.
+   * <p>
+   * Implementations should provide an optimised method to return locations to
+   * highlight on a visible portion of an alignment.
+   * 
+   * @param sequence
+   * @param start
+   *          first column of range (base 0, inclusive)
+   * @param end
+   *          last column of range base 0, inclusive)
+   * @return int[]
+   */
+  int[] getResults(SequenceI sequence, int start, int end);
+
+  /**
+   * Returns the number of matches found
+   * 
+   * @return
+   */
+  int getSize();
+
+  /**
+   * Returns true if no search result matches are held.
+   * 
+   * @return
+   */
+  boolean isEmpty();
+
+  /**
+   * Returns the list of matches.
+   * 
+   * @return
+   */
+  List<SearchResultMatchI> getResults();
+
+  /**
+   * Set bits in a bitfield for all columns in the given sequence collection
+   * that are highlighted
+   * 
+   * @param sqcol
+   *          the set of sequences to search for highlighted regions
+   * @param bs
+   *          bitset to set
+   * @return number of bits set
+   */
+  int markColumns(SequenceCollectionI sqcol, BitSet bs);
+}
\ No newline at end of file
index c75d6f2..15f54b9 100755 (executable)
@@ -208,7 +208,9 @@ public class SequenceFeature
     }
 
     SequenceFeature sf = (SequenceFeature) o;
-    if (begin != sf.begin || end != sf.end || score != sf.score)
+    boolean sameScore = Float.isNaN(score) ? Float.isNaN(sf.score)
+            : score == sf.score;
+    if (begin != sf.begin || end != sf.end || !sameScore)
     {
       return false;
     }
@@ -530,4 +532,20 @@ public class SequenceFeature
     return s.hashCode() + getBegin() + getEnd() + (int) getScore()
             + getStrand();
   }
+
+  /**
+   * Answers true if the feature's start/end values represent two related
+   * positions, rather than ends of a range. Such features may be visualised or
+   * reported differently to features on a range.
+   */
+  public boolean isContactFeature()
+  {
+    // TODO abstract one day to a FeatureType class
+    if ("disulfide bond".equalsIgnoreCase(type)
+            || "disulphide bond".equalsIgnoreCase(type))
+    {
+      return true;
+    }
+    return false;
+  }
 }
index ca90003..9245761 100755 (executable)
@@ -527,7 +527,7 @@ public class SequenceGroup implements AnnotatedCollectionI
     boolean upd = false;
     try
     {
-      ProfileI[] cnsns = AAFrequency.calculate(sequences, startRes,
+      ProfilesI cnsns = AAFrequency.calculate(sequences, startRes,
               endRes + 1, showSequenceLogo);
       if (consensus != null)
       {
@@ -599,9 +599,9 @@ public class SequenceGroup implements AnnotatedCollectionI
     c.completeAnnotations(conservation, null, startRes, endRes + 1);
   }
 
-  public ProfileI[] consensusData = null;
+  public ProfilesI consensusData = null;
 
-  private void _updateConsensusRow(ProfileI[] cnsns, long nseq)
+  private void _updateConsensusRow(ProfilesI cnsns, long nseq)
   {
     if (consensus == null)
     {
index f536819..4033dcc 100644 (file)
@@ -16,6 +16,12 @@ package jalview.ext.android;
  * limitations under the License.
  */
 
+/*
+ * Copied to Jalview September 2016.
+ * Only the members of this class required for SparseIntArray were copied.
+ * Method binarySearch(short[] array, int size, short value) added to support
+ * SparseShortArray.
+ */
 class ContainerHelpers
 {
   static final boolean[] EMPTY_BOOLEANS = new boolean[0];
@@ -83,7 +89,7 @@ class ContainerHelpers
     while (lo <= hi)
     {
       final int mid = (lo + hi) >>> 1;
-      final int midVal = array[mid];
+      final short midVal = array[mid];
       if (midVal < value)
       {
         lo = mid + 1;
index 2b9c4af..fcd4f1f 100644 (file)
@@ -40,6 +40,13 @@ package jalview.ext.android;
  * order in the case of <code>valueAt(int)<code>.
  * </p>
  */
+
+/*
+ * Imported into Jalview September 2016
+ * Change log:
+ *   Sep 2016 method add(int, int) added for more efficient increment of counts
+ *            (a single binary search, rather than one on read and one on write)
+ */
 public class SparseIntArray implements Cloneable
 {
   private int[] mKeys;
index 375d745..f961f55 100644 (file)
@@ -40,12 +40,15 @@ package jalview.ext.android;
  * order in the case of <code>valueAt(int)<code>.
  * </p>
  */
-/**
- * A copy of SparseShortArray designed to store short values (to minimise space
- * usage).
+
+/*
+ * Added to Jalview September 2016. A copy of SparseIntArray designed to store
+ * short values (to minimise space usage).
  * <p>
- * Note that operations append, put, add throw ArithmeticException if the
- * resulting value overflows the range of a short.
+ * Note that operations append, put, add throw ArithmeticException if either the
+ * key or the resulting value overflows the range of a short. Calling code
+ * should trap and handle this, for example by switching to using a
+ * SparseIntArray instead.
  */
 public class SparseShortArray implements Cloneable
 {
index fbac400..7a394f7 100644 (file)
@@ -49,8 +49,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import javajs.awt.Dimension;
-
 import org.jmol.adapter.smarter.SmarterJmolAdapter;
 import org.jmol.api.JmolAppConsoleInterface;
 import org.jmol.api.JmolSelectionListener;
@@ -74,7 +72,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   Vector<String> atomsPicked = new Vector<String>();
 
-  public Vector<String> chainNames;
+  private List<String> chainNames;
 
   Hashtable<String, String> chainFile;
 
@@ -99,10 +97,10 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   public Viewer viewer;
 
   public JalviewJmolBinding(StructureSelectionManager ssm,
-          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
+          PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
           String protocol)
   {
-    super(ssm, pdbentry, sequenceIs, chains, protocol);
+    super(ssm, pdbentry, sequenceIs, protocol);
     /*
      * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
      * "jalviewJmol", ap.av.applet .getDocumentBase(),
@@ -1083,7 +1081,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     fileLoadingError = null;
     String[] oldmodels = modelFileNames;
     modelFileNames = null;
-    chainNames = new Vector<String>();
+    chainNames = new ArrayList<String>();
     chainFile = new Hashtable<String, String>();
     boolean notifyLoaded = false;
     String[] modelfilenames = getPdbFile();
@@ -1143,6 +1141,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       for (int pe = 0; pe < getPdbCount(); pe++)
       {
         boolean matches = false;
+        addSequence(pe, getSequence()[pe]);
         if (fileName == null)
         {
           if (false)
@@ -1194,7 +1193,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
             String chid = new String(pdb.getId() + ":"
                     + pdb.getChains().elementAt(i).id);
             chainFile.put(chid, fileName);
-            chainNames.addElement(chid);
+            chainNames.add(chid);
           }
           notifyLoaded = true;
         }
@@ -1242,6 +1241,12 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     setLoadingFromArchive(false);
   }
 
+  @Override
+  public List<String> getChainNames()
+  {
+    return chainNames;
+  }
+
   public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
   {
     notifyAtomPicked(iatom, strMeasure, null);
@@ -1404,7 +1409,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   }
 
   @Override
-  public Dimension resizeInnerPanel(String data)
+  public int[] resizeInnerPanel(String data)
   {
     // Jalview doesn't honour resize panel requests
     return null;
index b2ba256..180da8f 100644 (file)
@@ -38,8 +38,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import javajs.awt.Dimension;
-
 import org.jmol.api.JmolStatusListener;
 import org.jmol.api.JmolViewer;
 import org.jmol.c.CBK;
@@ -626,7 +624,7 @@ public class JmolParser extends StructureFile implements JmolStatusListener
    * Not implemented - returns null
    */
   @Override
-  public Dimension resizeInnerPanel(String data)
+  public int[] resizeInnerPanel(String data)
   {
     return null;
   }
index 501e345..327d787 100644 (file)
@@ -41,6 +41,7 @@ import jalview.util.MessageManager;
 import java.awt.Color;
 import java.net.BindException;
 import java.util.ArrayList;
+import java.util.Hashtable;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -64,6 +65,10 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
 
   private static final String ALPHACARBON = "CA";
 
+  private List<String> chainNames = new ArrayList<String>();
+
+  private Hashtable<String, String> chainFile = new Hashtable<String, String>();
+
   /*
    * Object through which we talk to Chimera
    */
@@ -194,10 +199,9 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    * @param protocol
    */
   public JalviewChimeraBinding(StructureSelectionManager ssm,
-          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
-          String protocol)
+          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String protocol)
   {
-    super(ssm, pdbentry, sequenceIs, chains, protocol);
+    super(ssm, pdbentry, sequenceIs, protocol);
     viewer = new ChimeraManager(new StructureManager(true));
   }
 
@@ -277,11 +281,14 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     boolean first = true;
     for (String chain : toshow)
     {
+      int modelNumber = getModelNoForChain(chain);
+      String showChainCmd = modelNumber == -1 ? "" : modelNumber + ":."
+              + chain.split(":")[1];
       if (!first)
       {
         cmd.append(",");
       }
-      cmd.append(":.").append(chain);
+      cmd.append(showChainCmd);
       first = false;
     }
 
@@ -290,7 +297,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
      * window, but it looks more helpful not to (easier to relate chains to the
      * whole)
      */
-    final String command = "~display #*; ~ribbon #*; ribbon "
+    final String command = "~display #*; ~ribbon #*; ribbon :"
             + cmd.toString();
     sendChimeraCommand(command, false);
   }
@@ -801,18 +808,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     {
       return new String[0];
     }
-    // if (modelFileNames == null)
-    // {
-    // Collection<ChimeraModel> chimodels = viewer.getChimeraModels();
-    // _modelFileNameMap = new int[chimodels.size()];
-    // int j = 0;
-    // for (ChimeraModel chimodel : chimodels)
-    // {
-    // String mdlName = chimodel.getModelName();
-    // }
-    // modelFileNames = new String[j];
-    // // System.arraycopy(mset, 0, modelFileNames, 0, j);
-    // }
 
     return chimeraMaps.keySet().toArray(
             modelFileNames = new String[chimeraMaps.size()]);
@@ -1105,35 +1100,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
-   * Returns a list of chains mapped in this viewer. Note this list is not
-   * currently scoped per structure.
-   * 
-   * @return
-   */
-  public List<String> getChainNames()
-  {
-    List<String> names = new ArrayList<String>();
-    String[][] allNames = getChains();
-    if (allNames != null)
-    {
-      for (String[] chainsForPdb : allNames)
-      {
-        if (chainsForPdb != null)
-        {
-          for (String chain : chainsForPdb)
-          {
-            if (chain != null && !names.contains(chain))
-            {
-              names.add(chain);
-            }
-          }
-        }
-      }
-    }
-    return names;
-  }
-
-  /**
    * Send a 'focus' command to Chimera to recentre the visible display
    */
   public void focusView()
@@ -1168,4 +1134,30 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       sm.highlightStructure(this, seq, positions);
     }
   }
+
+  @Override
+  public List<String> getChainNames()
+  {
+    return chainNames;
+  }
+
+  public Hashtable<String, String> getChainFile()
+  {
+    return chainFile;
+  }
+
+  public List<ChimeraModel> getChimeraModelByChain(String chain)
+  {
+    return chimeraMaps.get(chainFile.get(chain));
+  }
+
+  public int getModelNoForChain(String chain)
+  {
+    List<ChimeraModel> foundModels = getChimeraModelByChain(chain);
+    if (foundModels != null && !foundModels.isEmpty())
+    {
+      return foundModels.get(0).getModelNumber();
+    }
+    return -1;
+  }
 }
index 20fa657..6a637e3 100644 (file)
@@ -670,6 +670,16 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           toggleHiddenRegions(toggleSeqs, toggleCols);
           break;
         }
+        case KeyEvent.VK_B:
+        {
+          boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
+          boolean modifyExisting = true; // always modify, don't clear
+                                         // evt.isShiftDown();
+          boolean invertHighlighted = evt.isAltDown();
+          avc.markHighlightedColumns(invertHighlighted, modifyExisting,
+                  toggleSel);
+          break;
+        }
         case KeyEvent.VK_PAGE_UP:
           if (viewport.getWrapAlignment())
           {
@@ -1341,14 +1351,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void htmlMenuItem_actionPerformed(ActionEvent e)
   {
-    new HtmlSvgOutput(null, alignPanel);
+    HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
+    htmlSVG.exportHTML(null);
   }
 
   @Override
   public void bioJSMenuItem_actionPerformed(ActionEvent e)
   {
-    BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel, this);
-    bjs.exportJalviewAlignmentAsBioJsHtmlFile(null);
+    BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
+    bjs.exportHTML(null);
   }
 
   public void createImageMap(File file, String image)
@@ -2908,8 +2919,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     viewport.setFollowHighlight(state);
     if (state)
     {
-      alignPanel.scrollToPosition(
-              alignPanel.getSeqPanel().seqCanvas.searchResults, false);
+      alignPanel.scrollToPosition(viewport.getSearchResults(), false);
     }
   }
 
@@ -5931,6 +5941,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     return false;
   }
+
+  @Override
+  protected void selectHighlightedColumns_actionPerformed(
+          ActionEvent actionEvent)
+  {
+    // include key modifier check in case user selects from menu
+    avc.markHighlightedColumns(
+            (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0,
+            true,
+            (actionEvent.getModifiers() & (ActionEvent.META_MASK | ActionEvent.CTRL_MASK)) != 0);
+  }
 }
 
 class PrintThread extends Thread
index d0a0f11..03aee5d 100644 (file)
@@ -37,6 +37,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -1042,7 +1043,7 @@ public class AlignViewport extends AlignmentViewport implements
      * there is no complement, or it is not following highlights, or no mapping
      * is found, the result will be empty.
      */
-    SearchResults sr = new SearchResults();
+    SearchResultsI sr = new SearchResults();
     int verticalOffset = findComplementScrollTarget(sr);
     if (!sr.isEmpty())
     {
index 4db029c..e61b042 100644 (file)
@@ -25,7 +25,7 @@ import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.bin.Cache;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -297,7 +297,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * Highlight the given results on the alignment.
    * 
    */
-  public void highlightSearchResults(SearchResults results)
+  public void highlightSearchResults(SearchResultsI results)
   {
     scrollToPosition(results);
     getSeqPanel().seqCanvas.highlightSearchResults(results);
@@ -309,7 +309,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * 
    * @param results
    */
-  public boolean scrollToPosition(SearchResults results)
+  public boolean scrollToPosition(SearchResultsI results)
   {
     return scrollToPosition(results, 0, true, false);
   }
@@ -322,7 +322,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @param redrawOverview
    * @return
    */
-  public boolean scrollToPosition(SearchResults searchResults,
+  public boolean scrollToPosition(SearchResultsI searchResults,
           boolean redrawOverview)
   {
     return scrollToPosition(searchResults, 0, redrawOverview, false);
@@ -342,7 +342,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    *          if true, try to centre the search results horizontally in the view
    * @return false if results were not found
    */
-  public boolean scrollToPosition(SearchResults results,
+  public boolean scrollToPosition(SearchResultsI results,
           int verticalOffset, boolean redrawOverview, boolean centre)
   {
     int startv, endv, starts, ends;
@@ -956,11 +956,11 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
     if (av.getWrapAlignment())
     {
-      return printWrappedAlignment(pg, pwidth, pheight, pi);
+      return printWrappedAlignment(pwidth, pheight, pi, pg);
     }
     else
     {
-      return printUnwrapped(pg, pwidth, pheight, pi);
+      return printUnwrapped(pwidth, pheight, pi, pg, pg);
     }
   }
 
@@ -981,84 +981,103 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @throws PrinterException
    *           DOCUMENT ME!
    */
-  public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)
+  /**
+   * Draws the alignment image, including sequence ids, sequences, and
+   * annotation labels and annotations if shown, on either one or two Graphics
+   * context.
+   * 
+   * @param pageWidth
+   * @param pageHeight
+   * @param pi
+   * @param idGraphics
+   *          the graphics context for sequence ids and annotation labels
+   * @param alignmentGraphics
+   *          the graphics context for sequences and annotations (may or may not
+   *          be the same context as idGraphics)
+   * @return
+   * @throws PrinterException
+   */
+  public int printUnwrapped(int pageWidth, int pageHeight, int pi,
+          Graphics idGraphics, Graphics alignmentGraphics)
           throws PrinterException
   {
-    int idWidth = getVisibleIdWidth(false);
-    FontMetrics fm = getFontMetrics(av.getFont());
-    int scaleHeight = av.getCharHeight() + fm.getDescent();
+    final int idWidth = getVisibleIdWidth(false);
 
-    pg.setColor(Color.white);
-    pg.fillRect(0, 0, pwidth, pheight);
-    pg.setFont(av.getFont());
-
-    // //////////////////////////////////
-    // / How many sequences and residues can we fit on a printable page?
-    int totalRes = (pwidth - idWidth) / av.getCharWidth();
+    /*
+     * Get the horizontal offset to where we draw the sequences.
+     * This is idWidth if using a single Graphics context, else zero.
+     */
+    final int alignmentGraphicsOffset = idGraphics != alignmentGraphics ? 0 : idWidth;
 
-    int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1;
+    FontMetrics fm = getFontMetrics(av.getFont());
+    int charHeight = av.getCharHeight();
+    int scaleHeight = charHeight + fm.getDescent();
 
-    int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
+    idGraphics.setColor(Color.white);
+    idGraphics.fillRect(0, 0, pageWidth, pageHeight);
+    idGraphics.setFont(av.getFont());
 
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int startRes;
+    /*
+     * How many sequences and residues can we fit on a printable page?
+     */
+    int totalRes = (pageWidth - idWidth) / av.getCharWidth();
 
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int endRes;
+    int totalSeq = (pageHeight - scaleHeight) / charHeight - 1;
 
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int startSeq;
+    int alignmentWidth = av.getAlignment().getWidth();
+    int pagesWide = (alignmentWidth / totalRes) + 1;
 
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int endSeq;
-    startRes = (pi % pagesWide) * totalRes;
-    endRes = (startRes + totalRes) - 1;
+    final int startRes = (pi % pagesWide) * totalRes;
+    int endRes = (startRes + totalRes) - 1;
 
-    if (endRes > (av.getAlignment().getWidth() - 1))
+    if (endRes > (alignmentWidth - 1))
     {
-      endRes = av.getAlignment().getWidth() - 1;
+      endRes = alignmentWidth - 1;
     }
 
-    startSeq = (pi / pagesWide) * totalSeq;
-    endSeq = startSeq + totalSeq;
+    final int startSeq = (pi / pagesWide) * totalSeq;
+    int endSeq = startSeq + totalSeq;
 
-    if (endSeq > av.getAlignment().getHeight())
+    int alignmentHeight = av.getAlignment().getHeight();
+    if (endSeq > alignmentHeight)
     {
-      endSeq = av.getAlignment().getHeight();
+      endSeq = alignmentHeight;
     }
 
-    int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
-            * pheight;
+    int pagesHigh = ((alignmentHeight / totalSeq) + 1)
+            * pageHeight;
 
     if (av.isShowAnnotation())
     {
       pagesHigh += getAnnotationPanel().adjustPanelHeight() + 3;
     }
 
-    pagesHigh /= pheight;
+    pagesHigh /= pageHeight;
 
     if (pi >= (pagesWide * pagesHigh))
     {
       return Printable.NO_SUCH_PAGE;
     }
+    final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight
+            + 3;
 
-    // draw Scale
-    pg.translate(idWidth, 0);
-    getScalePanel().drawScale(pg, startRes, endRes, pwidth - idWidth,
-            scaleHeight);
-    pg.translate(-idWidth, scaleHeight);
+    /*
+     * draw the Scale at horizontal offset, then reset to top left (0, 0)
+     */
+    alignmentGraphics.translate(alignmentGraphicsOffset, 0);
+    getScalePanel().drawScale(alignmentGraphics, startRes, endRes,
+            pageWidth - idWidth, scaleHeight);
+    alignmentGraphics.translate(-alignmentGraphicsOffset, 0);
 
-    // //////////////
-    // Draw the ids
+    /*
+     * Draw the sequence ids, offset for scale height,
+     * then reset to top left (0, 0)
+     */
+    idGraphics.translate(0, scaleHeight);
+    idGraphics.setFont(getIdPanel().getIdCanvas().getIdfont());
     Color currentColor = null;
     Color currentTextColor = null;
 
-    pg.setFont(getIdPanel().getIdCanvas().getIdfont());
-
     SequenceI seq;
     for (int i = startSeq; i < endSeq; i++)
     {
@@ -1066,6 +1085,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
       if ((av.getSelectionGroup() != null)
               && av.getSelectionGroup().getSequences(null).contains(seq))
       {
+        /*
+         * gray out ids of sequences in selection group (if any)
+         */
         currentColor = Color.gray;
         currentTextColor = Color.black;
       }
@@ -1075,45 +1097,58 @@ public class AlignmentPanel extends GAlignmentPanel implements
         currentTextColor = Color.black;
       }
 
-      pg.setColor(currentColor);
-      pg.fillRect(0, (i - startSeq) * av.getCharHeight(), idWidth,
-              av.getCharHeight());
+      idGraphics.setColor(currentColor);
+      idGraphics.fillRect(0, (i - startSeq) * charHeight, idWidth,
+              charHeight);
 
-      pg.setColor(currentTextColor);
+      idGraphics.setColor(currentTextColor);
 
       int xPos = 0;
+      String displayId = seq.getDisplayId(av.getShowJVSuffix());
       if (av.isRightAlignIds())
       {
-        fm = pg.getFontMetrics();
+        fm = idGraphics.getFontMetrics();
         xPos = idWidth
-                - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
+                - fm.stringWidth(displayId)
                 - 4;
       }
 
-      pg.drawString(seq.getDisplayId(av.getShowJVSuffix()), xPos,
-              (((i - startSeq) * av.getCharHeight()) + av.getCharHeight())
-                      - (av.getCharHeight() / 5));
+      idGraphics.drawString(displayId, xPos,
+              (((i - startSeq) * charHeight) + charHeight)
+                      - (charHeight / 5));
     }
+    idGraphics.setFont(av.getFont());
+    idGraphics.translate(0, -scaleHeight);
 
-    pg.setFont(av.getFont());
+    /*
+     * draw the sequences, offset for scale height, and id width (if using a
+     * single graphics context), then reset to (0, scale height)
+     */
+    alignmentGraphics.translate(alignmentGraphicsOffset, scaleHeight);
+    getSeqPanel().seqCanvas.drawPanel(alignmentGraphics, startRes, endRes,
+            startSeq, endSeq, 0);
+    alignmentGraphics.translate(-alignmentGraphicsOffset, 0);
 
-    // draw main sequence panel
-    pg.translate(idWidth, 0);
-    getSeqPanel().seqCanvas.drawPanel(pg, startRes, endRes, startSeq,
-            endSeq, 0);
-
-    if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight()))
-    {
-      // draw annotation - need to offset for current scroll position
-      int offset = -getAlabels().getScrollOffset();
-      pg.translate(0, offset);
-      pg.translate(-idWidth - 3, (endSeq - startSeq) * av.getCharHeight()
-              + 3);
-      getAlabels().drawComponent(pg, idWidth);
-      pg.translate(idWidth + 3, 0);
+    if (av.isShowAnnotation() && (endSeq == alignmentHeight))
+    {
+      /*
+       * draw annotation labels; drawComponent() translates by
+       * getScrollOffset(), so compensate for that first;
+       * then reset to (0, scale height)
+       */
+      int offset = getAlabels().getScrollOffset();
+      idGraphics.translate(0, -offset);
+      idGraphics.translate(0, alignmentDrawnHeight);
+      getAlabels().drawComponent(idGraphics, idWidth);
+      idGraphics.translate(0, -alignmentDrawnHeight);
+
+      /*
+       * draw the annotations starting at 
+       * (idOffset, alignmentHeight) from (0, scaleHeight)
+       */
+      alignmentGraphics.translate(alignmentGraphicsOffset, alignmentDrawnHeight);
       getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
-              pg, -1, startRes, endRes + 1);
-      pg.translate(0, -offset);
+              alignmentGraphics, -1, startRes, endRes + 1);
     }
 
     return Printable.PAGE_EXISTS;
@@ -1136,8 +1171,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @throws PrinterException
    *           DOCUMENT ME!
    */
-  public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,
-          int pi) throws PrinterException
+  public int printWrappedAlignment(int pwidth, int pheight, int pi,
+          Graphics pg) throws PrinterException
   {
     int annotationHeight = 0;
     AnnotationLabels labels = null;
@@ -1264,8 +1299,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     if (onscreen
             || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
     {
-      return (getIdPanel().getWidth() > 0 ? getIdPanel().getWidth()
-              : calculateIdWidth().width + 4);
+      int w = getIdPanel().getWidth();
+      return (w > 0 ? w : calculateIdWidth().width + 4);
     }
     return idwidth.intValue() + 4;
   }
@@ -1312,21 +1347,23 @@ public class AlignmentPanel extends GAlignmentPanel implements
                 aDimension.getWidth(), aDimension.getHeight()
                         + boarderBottomOffset, file, imageTitle,
                 alignFrame, pSessionId, headless);
+        Graphics graphics = im.getGraphics();
         if (av.getWrapAlignment())
         {
-          if (im.getGraphics() != null)
+          if (graphics != null)
           {
-            printWrappedAlignment(im.getGraphics(), aDimension.getWidth(),
-                    aDimension.getHeight() + boarderBottomOffset, 0);
+            printWrappedAlignment(aDimension.getWidth(),
+                    aDimension.getHeight() + boarderBottomOffset, 0,
+                    graphics);
             im.writeImage();
           }
         }
         else
         {
-          if (im.getGraphics() != null)
+          if (graphics != null)
           {
-            printUnwrapped(im.getGraphics(), aDimension.getWidth(),
-                    aDimension.getHeight(), 0);
+            printUnwrapped(aDimension.getWidth(), aDimension.getHeight(),
+                    0, graphics, graphics);
             im.writeImage();
           }
         }
@@ -1411,7 +1448,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
   public void makePNGImageMap(File imgMapFile, String imageName)
   {
-    // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS
+    // /////ONLY WORKS WITH NON WRAPPED ALIGNMENTS
     // ////////////////////////////////////////////
     int idWidth = getVisibleIdWidth(false);
     FontMetrics fm = getFontMetrics(av.getFont());
@@ -1425,7 +1462,6 @@ public class AlignmentPanel extends GAlignmentPanel implements
       {
         int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
                 .getAlignment().getWidth(), g, gSize, f, fSize, sy;
-        StringBuffer text = new StringBuffer();
         PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
         out.println(jalview.io.HTMLOutput.getImageMapHTML());
         out.println("<img src=\"" + imageName
@@ -1441,7 +1477,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
           SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
           for (res = 0; res < alwidth; res++)
           {
-            text = new StringBuffer();
+            StringBuilder text = new StringBuilder();
             String triplet = null;
             if (av.getAlignment().isNucleotide())
             {
@@ -1465,18 +1501,20 @@ public class AlignmentPanel extends GAlignmentPanel implements
             {
               if (text.length() < 1)
               {
-                text.append("<area shape=\"rect\" coords=\""
-                        + (idWidth + res * av.getCharWidth()) + "," + sy
-                        + "," + (idWidth + (res + 1) * av.getCharWidth())
-                        + "," + (av.getCharHeight() + sy) + "\""
-                        + " onMouseOver=\"toolTip('" + alIndex + " "
-                        + triplet);
+                text.append("<area shape=\"rect\" coords=\"")
+                        .append((idWidth + res * av.getCharWidth()))
+                        .append(",").append(sy).append(",")
+                        .append((idWidth + (res + 1) * av.getCharWidth()))
+                        .append(",").append((av.getCharHeight() + sy))
+                        .append("\"").append(" onMouseOver=\"toolTip('")
+                        .append(alIndex).append(" ").append(triplet);
               }
 
               if (groups[g].getStartRes() < res
                       && groups[g].getEndRes() > res)
               {
-                text.append("<br><em>" + groups[g].getName() + "</em>");
+                text.append("<br><em>").append(groups[g].getName())
+                        .append("</em>");
               }
             }
 
@@ -1484,12 +1522,13 @@ public class AlignmentPanel extends GAlignmentPanel implements
             {
               if (text.length() < 1)
               {
-                text.append("<area shape=\"rect\" coords=\""
-                        + (idWidth + res * av.getCharWidth()) + "," + sy
-                        + "," + (idWidth + (res + 1) * av.getCharWidth())
-                        + "," + (av.getCharHeight() + sy) + "\""
-                        + " onMouseOver=\"toolTip('" + alIndex + " "
-                        + triplet);
+                text.append("<area shape=\"rect\" coords=\"")
+                        .append((idWidth + res * av.getCharWidth()))
+                        .append(",").append(sy).append(",")
+                        .append((idWidth + (res + 1) * av.getCharWidth()))
+                        .append(",").append((av.getCharHeight() + sy))
+                        .append("\"").append(" onMouseOver=\"toolTip('")
+                        .append(alIndex).append(" ").append(triplet);
               }
               fSize = features.length;
               for (f = 0; f < fSize; f++)
@@ -1498,15 +1537,15 @@ public class AlignmentPanel extends GAlignmentPanel implements
                 if ((features[f].getBegin() <= seq.findPosition(res))
                         && (features[f].getEnd() >= seq.findPosition(res)))
                 {
-                  if (features[f].getType().equals("disulfide bond"))
+                  if (features[f].isContactFeature())
                   {
                     if (features[f].getBegin() == seq.findPosition(res)
                             || features[f].getEnd() == seq
                                     .findPosition(res))
                     {
-                      text.append("<br>disulfide bond "
-                              + features[f].getBegin() + ":"
-                              + features[f].getEnd());
+                      text.append("<br>").append(features[f].getType())
+                              .append(" ").append(features[f].getBegin())
+                              .append(":").append(features[f].getEnd());
                     }
                   }
                   else
@@ -1517,13 +1556,13 @@ public class AlignmentPanel extends GAlignmentPanel implements
                             && !features[f].getType().equals(
                                     features[f].getDescription()))
                     {
-                      text.append(" " + features[f].getDescription());
+                      text.append(" ").append(features[f].getDescription());
                     }
 
                     if (features[f].getValue("status") != null)
                     {
-                      text.append(" (" + features[f].getValue("status")
-                              + ")");
+                      text.append(" (").append(features[f].getValue("status"))
+                              .append(")");
                     }
                   }
                 }
@@ -1788,14 +1827,14 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @param verticalOffset
    *          the number of visible sequences to show above the mapped region
    */
-  public void scrollToCentre(SearchResults sr, int verticalOffset)
+  public void scrollToCentre(SearchResultsI sr, int verticalOffset)
   {
     /*
      * To avoid jumpy vertical scrolling (if some sequences are gapped or not
      * mapped), we can make the scroll-to location a sequence above the one
      * actually mapped.
      */
-    SequenceI mappedTo = sr.getResultSequence(0);
+    SequenceI mappedTo = sr.getResults().get(0).getSequence();
     List<SequenceI> seqs = av.getAlignment().getSequences();
 
     /*
index 1c0dfe6..d7e8305 100644 (file)
@@ -50,7 +50,6 @@ import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.io.BufferedReader;
@@ -67,7 +66,6 @@ import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JColorChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
-import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JSplitPane;
@@ -131,7 +129,7 @@ public class AppJmol extends StructureViewerBase
     // / TODO: check if protocol is needed to be set, and if chains are
     // autodiscovered.
     jmb = new AppJmolBinding(this, ap.getStructureSelectionManager(),
-            pdbentrys, seqs, null, null);
+            pdbentrys, seqs, null);
 
     jmb.setLoadingFromArchive(true);
     addAlignmentPanel(ap);
@@ -301,7 +299,7 @@ public class AppJmol extends StructureViewerBase
   {
     progressBar = ap.alignFrame;
     jmb = new AppJmolBinding(this, ap.getStructureSelectionManager(),
-            pdbentrys, seqs, null, null);
+            pdbentrys, seqs, null);
     addAlignmentPanel(ap);
     useAlignmentPanelForColourbyseq(ap);
     if (pdbentrys.length > 1)
@@ -394,57 +392,12 @@ public class AppJmol extends StructureViewerBase
     jmb.setFinishedInit(true);
   }
 
-  void setChainMenuItems(Vector<String> chains)
-  {
-    chainMenu.removeAll();
-    if (chains == null)
-    {
-      return;
-    }
-    JMenuItem menuItem = new JMenuItem(
-            MessageManager.getString("label.all"));
-    menuItem.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent evt)
-      {
-        allChainsSelected = true;
-        for (int i = 0; i < chainMenu.getItemCount(); i++)
-        {
-          if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
-          {
-            ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
-          }
-        }
-        centerViewer();
-        allChainsSelected = false;
-      }
-    });
-
-    chainMenu.add(menuItem);
-
-    for (String chain : chains)
-    {
-      menuItem = new JCheckBoxMenuItem(chain, true);
-      menuItem.addItemListener(new ItemListener()
-      {
-        @Override
-        public void itemStateChanged(ItemEvent evt)
-        {
-          if (!allChainsSelected)
-          {
-            centerViewer();
-          }
-        }
-      });
 
-      chainMenu.add(menuItem);
-    }
-  }
 
   boolean allChainsSelected = false;
 
-  void centerViewer()
+  @Override
+  void showSelectedChains()
   {
     Vector<String> toshow = new Vector<String>();
     for (int i = 0; i < chainMenu.getItemCount(); i++)
@@ -1075,7 +1028,7 @@ public class AppJmol extends StructureViewerBase
       repaint();
       return;
     }
-    setChainMenuItems(jmb.chainNames);
+    setChainMenuItems(jmb.getChainNames());
 
     this.setTitle(jmb.getViewerTitle());
     if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1)
index ffa34f8..a6d699f 100644 (file)
@@ -42,10 +42,9 @@ public class AppJmolBinding extends JalviewJmolBinding
   private FeatureRenderer fr = null;
 
   public AppJmolBinding(AppJmol appJmol, StructureSelectionManager sSm,
-          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
-          String protocol)
+          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String protocol)
   {
-    super(sSm, pdbentry, sequenceIs, chains, protocol);
+    super(sSm, pdbentry, sequenceIs, protocol);
     appJmolWindow = appJmol;
   }
 
index ce719d0..fe12f40 100644 (file)
@@ -31,6 +31,7 @@ import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
+import jalview.io.StructureFile;
 import jalview.schemes.BuriedColourScheme;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.HelixColourScheme;
@@ -46,7 +47,6 @@ import jalview.util.Platform;
 import jalview.ws.dbsources.Pdb;
 
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.io.BufferedReader;
@@ -66,7 +66,6 @@ import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JColorChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
-import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
@@ -248,10 +247,8 @@ public class ChimeraViewFrame extends StructureViewerBase
   {
     createProgressBar();
     // FIXME extractChains needs pdbentries to match IDs to PDBEntry(s) on seqs
-    String[][] chains = extractChains(seqs);
     jmb = new JalviewChimeraBindingModel(this,
-            ap.getStructureSelectionManager(), pdbentrys, seqs, chains,
-            null);
+            ap.getStructureSelectionManager(), pdbentrys, seqs, null);
     addAlignmentPanel(ap);
     useAlignmentPanelForColourbyseq(ap);
     if (pdbentrys.length > 1)
@@ -278,41 +275,7 @@ public class ChimeraViewFrame extends StructureViewerBase
 
   }
 
-  /**
-   * Retrieve chains for sequences by inspecting their PDB refs. The hope is
-   * that the first will be to the sequence's own chain. Really need a more
-   * managed way of doing this.
-   * 
-   * @param seqs
-   * @return
-   */
-  protected String[][] extractChains(SequenceI[][] seqs)
-  {
-    String[][] chains = new String[seqs.length][];
-    for (int i = 0; i < seqs.length; i++)
-    {
-      chains[i] = new String[seqs[i].length];
-      int seqno = 0;
-      for (SequenceI seq : seqs[i])
-      {
-        String chain = null;
-        if (seq.getDatasetSequence() != null)
-        {
-          Vector<PDBEntry> pdbrefs = seq.getDatasetSequence()
-                  .getAllPDBEntries();
-          if (pdbrefs != null && pdbrefs.size() > 0)
-          {
-            // FIXME: SequenceI.PDBEntry[0] chain mapping used for
-            // ChimeraViewFrame. Is this even used ???
 
-            chain = pdbrefs.get(0).getChainCode();
-          }
-        }
-        chains[i][seqno++] = chain;
-      }
-    }
-    return chains;
-  }
 
   /**
    * Create a new viewer from saved session state data including Chimera session
@@ -437,63 +400,11 @@ public class ChimeraViewFrame extends StructureViewerBase
     jmb.startChimeraListener();
   }
 
-  /**
-   * If the list is not empty, add menu items for 'All' and each individual
-   * chain to the "View | Show Chain" sub-menu. Multiple selections are allowed.
-   * 
-   * @param chainNames
-   */
-  void setChainMenuItems(List<String> chainNames)
-  {
-    chainMenu.removeAll();
-    if (chainNames == null || chainNames.isEmpty())
-    {
-      return;
-    }
-    JMenuItem menuItem = new JMenuItem(
-            MessageManager.getString("label.all"));
-    menuItem.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent evt)
-      {
-        allChainsSelected = true;
-        for (int i = 0; i < chainMenu.getItemCount(); i++)
-        {
-          if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
-          {
-            ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
-          }
-        }
-        showSelectedChains();
-        allChainsSelected = false;
-      }
-    });
-
-    chainMenu.add(menuItem);
-
-    for (String chainName : chainNames)
-    {
-      menuItem = new JCheckBoxMenuItem(chainName, true);
-      menuItem.addItemListener(new ItemListener()
-      {
-        @Override
-        public void itemStateChanged(ItemEvent evt)
-        {
-          if (!allChainsSelected)
-          {
-            showSelectedChains();
-          }
-        }
-      });
-
-      chainMenu.add(menuItem);
-    }
-  }
 
   /**
    * Show only the selected chain(s) in the viewer
    */
+  @Override
   void showSelectedChains()
   {
     List<String> toshow = new ArrayList<String>();
@@ -569,6 +480,7 @@ public class ChimeraViewFrame extends StructureViewerBase
     List<PDBEntry> filePDB = new ArrayList<PDBEntry>();
     List<Integer> filePDBpos = new ArrayList<Integer>();
     PDBEntry thePdbEntry = null;
+    StructureFile pdb = null;
     try
     {
       String[] curfiles = jmb.getPdbFile(); // files currently in viewer
@@ -677,8 +589,9 @@ public class ChimeraViewFrame extends StructureViewerBase
               stopProgressBar("", startTime);
             }
             // Explicitly map to the filename used by Chimera ;
-            jmb.getSsm().setMapping(jmb.getSequence()[pos],
+            pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
                     jmb.getChains()[pos], pe.getFile(), protocol);
+            stashFoundChains(pdb, pe.getFile());
           } catch (OutOfMemoryError oomerror)
           {
             new OOMWarning(
@@ -694,6 +607,7 @@ public class ChimeraViewFrame extends StructureViewerBase
           }
         }
       }
+      jmb.refreshGUI();
       jmb.setFinishedInit(true);
       jmb.setLoadingFromArchive(false);
 
@@ -729,6 +643,17 @@ public class ChimeraViewFrame extends StructureViewerBase
    * @return
    * @throws Exception
    */
+
+  private void stashFoundChains(StructureFile pdb, String file)
+  {
+    for (int i = 0; i < pdb.getChains().size(); i++)
+    {
+      String chid = new String(pdb.getId() + ":"
+              + pdb.getChains().elementAt(i).id);
+      jmb.getChainNames().add(chid);
+      jmb.getChainFile().put(chid, file);
+    }
+  }
   private String fetchPdbFile(PDBEntry processingEntry) throws Exception
   {
     // FIXME: this is duplicated code with Jmol frame ?
index 426ea32..83d1612 100644 (file)
@@ -22,6 +22,7 @@ package jalview.gui;
 
 import jalview.api.FeatureColourI;
 import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.schemes.FeatureColour;
@@ -200,7 +201,7 @@ public class FeatureRenderer extends
             start.setValue(new Integer(features[index].getBegin()));
             end.setValue(new Integer(features[index].getEnd()));
 
-            SearchResults highlight = new SearchResults();
+            SearchResultsI highlight = new SearchResults();
             highlight.addResult(sequences[0], features[index].getBegin(),
                     features[index].getEnd());
 
index 6bff69a..a8dbc38 100755 (executable)
@@ -20,7 +20,8 @@
  */
 package jalview.gui;
 
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultMatchI;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.jbgui.GFinder;
@@ -67,7 +68,7 @@ public class Finder extends GFinder
 
   int resIndex = -1;
 
-  SearchResults searchResults;
+  SearchResultsI searchResults;
 
   /**
    * Creates a new Finder object with no associated viewport or panel.
@@ -109,6 +110,7 @@ public class Finder extends GFinder
             KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel");
     getRootPane().getActionMap().put("Cancel", new AbstractAction()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         escapeActionPerformed();
@@ -130,6 +132,7 @@ public class Finder extends GFinder
    * 
    * @param e
    */
+  @Override
   public void findNext_actionPerformed(ActionEvent e)
   {
     if (getFocusedViewport())
@@ -143,6 +146,7 @@ public class Finder extends GFinder
    * 
    * @param e
    */
+  @Override
   public void findAll_actionPerformed(ActionEvent e)
   {
     if (getFocusedViewport())
@@ -198,19 +202,22 @@ public class Finder extends GFinder
    * @param e
    *          DOCUMENT ME!
    */
+  @Override
   public void createNewGroup_actionPerformed(ActionEvent e)
   {
     SequenceI[] seqs = new SequenceI[searchResults.getSize()];
     SequenceFeature[] features = new SequenceFeature[searchResults
             .getSize()];
 
-    for (int i = 0; i < searchResults.getSize(); i++)
+    int i = 0;
+    for (SearchResultMatchI match : searchResults.getResults())
     {
-      seqs[i] = searchResults.getResultSequence(i).getDatasetSequence();
+      seqs[i] = match.getSequence().getDatasetSequence();
 
       features[i] = new SequenceFeature(textfield.getText().trim(),
-              "Search Results", null, searchResults.getResultStart(i),
-              searchResults.getResultEnd(i), "Search Results");
+              "Search Results", null, match.getStart(), match.getEnd(),
+              "Search Results");
+      i++;
     }
 
     if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs,
@@ -256,7 +263,7 @@ public class Finder extends GFinder
 
     searchResults = finder.getSearchResults(); // find(regex,
     // caseSensitive.isSelected(), )
-    Vector idMatch = finder.getIdMatch();
+    Vector<SequenceI> idMatch = finder.getIdMatch();
     boolean haveResults = false;
     // set or reset the GUI
     if ((idMatch.size() > 0))
index e321a74..6a20872 100755 (executable)
@@ -109,8 +109,8 @@ public class IdPanel extends JPanel implements MouseListener,
     if (seq > -1 && seq < av.getAlignment().getHeight())
     {
       SequenceI sequence = av.getAlignment().getSequenceAt(seq);
-      StringBuffer tip = new StringBuffer(64);
-      seqAnnotReport.createSequenceAnnotationReport(tip, sequence,
+      StringBuilder tip = new StringBuilder(64);
+      seqAnnotReport.createTooltipAnnotationReport(tip, sequence,
               av.isShowDBRefs(), av.isShowNPFeats(),
               sp.seqCanvas.fr.getMinMax());
       setToolTipText(JvSwingUtils.wrapTooltip(true,
index 4bb7180..94724d1 100644 (file)
@@ -33,11 +33,12 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
 
   private FeatureRenderer fr = null;
 
+
   public JalviewChimeraBindingModel(ChimeraViewFrame chimeraViewFrame,
           StructureSelectionManager ssm, PDBEntry[] pdbentry,
-          SequenceI[][] sequenceIs, String[][] chains, String protocol)
+          SequenceI[][] sequenceIs, String protocol)
   {
-    super(ssm, pdbentry, sequenceIs, chains, protocol);
+    super(ssm, pdbentry, sequenceIs, protocol);
     cvf = chimeraViewFrame;
   }
 
index bb816cd..5825382 100644 (file)
@@ -1677,7 +1677,7 @@ public class PopupMenu extends JPopupMenu
   public void createSequenceDetailsReport(SequenceI[] sequences)
   {
     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
-    StringBuffer contents = new StringBuffer();
+    StringBuilder contents = new StringBuilder(128);
     for (SequenceI seq : sequences)
     {
       contents.append("<p><h2>"
@@ -1692,7 +1692,6 @@ public class PopupMenu extends JPopupMenu
                       seq,
                       true,
                       true,
-                      false,
                       (ap.getSeqPanel().seqCanvas.fr != null) ? ap
                               .getSeqPanel().seqCanvas.fr.getMinMax()
                               : null);
index 760ece0..d015292 100755 (executable)
@@ -21,7 +21,7 @@
 package jalview.gui;
 
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.ScaleRenderer;
@@ -62,8 +62,6 @@ public class SeqCanvas extends JComponent
 
   AlignViewport av;
 
-  SearchResults searchResults = null;
-
   boolean fastPaint = false;
 
   int LABEL_WEST;
@@ -740,10 +738,10 @@ public class SeqCanvas extends JComponent
 
       // / Highlight search Results once all sequences have been drawn
       // ////////////////////////////////////////////////////////
-      if (searchResults != null)
+      if (av.hasSearchResults())
       {
-        int[] visibleResults = searchResults.getResults(nextSeq, startRes,
-                endRes);
+        int[] visibleResults = av.getSearchResults().getResults(nextSeq,
+                startRes, endRes);
         if (visibleResults != null)
         {
           for (int r = 0; r < visibleResults.length; r += 2)
@@ -965,11 +963,11 @@ public class SeqCanvas extends JComponent
    * @param results
    *          DOCUMENT ME!
    */
-  public void highlightSearchResults(SearchResults results)
+  public void highlightSearchResults(SearchResultsI results)
   {
     img = null;
 
-    searchResults = results;
+    av.setSearchResults(results);
 
     repaint();
   }
index 3266fab..36fb052 100644 (file)
@@ -27,8 +27,9 @@ import jalview.commands.EditCommand.Action;
 import jalview.commands.EditCommand.Edit;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
-import jalview.datamodel.SearchResults.Match;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
@@ -124,7 +125,7 @@ public class SeqPanel extends JPanel implements MouseListener,
 
   private final SequenceAnnotationReport seqARep;
 
-  StringBuffer tooltipText = new StringBuffer();
+  StringBuilder tooltipText = new StringBuilder();
 
   String tmpString;
 
@@ -132,7 +133,7 @@ public class SeqPanel extends JPanel implements MouseListener,
 
   StructureSelectionManager ssm;
 
-  SearchResults lastSearchResults;
+  SearchResultsI lastSearchResults;
 
   /**
    * Creates a new SeqPanel object.
@@ -676,7 +677,7 @@ public class SeqPanel extends JPanel implements MouseListener,
    * the start of the highlighted region.
    */
   @Override
-  public void highlightSequence(SearchResults results)
+  public void highlightSequence(SearchResultsI results)
   {
     if (results == null || results.equals(lastSearchResults))
     {
@@ -785,7 +786,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       seqARep.appendFeatures(tooltipText, rpos, features,
               this.ap.getSeqPanel().seqCanvas.fr.getMinMax());
     }
-    if (tooltipText.length() == 6) // <html></html>
+    if (tooltipText.length() == 6) // <html>
     {
       setToolTipText(null);
       lastTooltip = null;
@@ -910,7 +911,7 @@ public class SeqPanel extends JPanel implements MouseListener,
    * 
    * @param results
    */
-  private void setStatusMessage(SearchResults results)
+  private void setStatusMessage(SearchResultsI results)
   {
     AlignmentI al = this.av.getAlignment();
     int sequenceIndex = al.findIndex(results);
@@ -919,7 +920,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       return;
     }
     SequenceI ds = al.getSequenceAt(sequenceIndex).getDatasetSequence();
-    for (Match m : results.getResults())
+    for (SearchResultMatchI m : results.getResults())
     {
       SequenceI seq = m.getSequence();
       if (seq.getDatasetSequence() != null)
@@ -1501,7 +1502,7 @@ public class SeqPanel extends JPanel implements MouseListener,
 
       if (features != null && features.size() > 0)
       {
-        SearchResults highlight = new SearchResults();
+        SearchResultsI highlight = new SearchResults();
         highlight.addResult(sequence, features.get(0).getBegin(), features
                 .get(0).getEnd());
         seqCanvas.highlightSearchResults(highlight);
index 3350f6c..21b6e4f 100644 (file)
@@ -83,6 +83,8 @@ public class StructureChooser extends GStructureChooser implements
 
   private boolean cachedPDBExists;
 
+  private static int MAX_QLENGHT = 7820;
+
   public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
           AlignmentPanel ap)
   {
@@ -259,7 +261,8 @@ public class StructureChooser extends GStructureChooser implements
     StringBuilder queryBuilder = new StringBuilder();
     Set<String> seqRefs = new LinkedHashSet<String>();
 
-    if (seq.getAllPDBEntries() != null)
+    if (seq.getAllPDBEntries() != null
+            && queryBuilder.length() < MAX_QLENGHT)
     {
       for (PDBEntry entry : seq.getAllPDBEntries())
       {
@@ -268,7 +271,6 @@ public class StructureChooser extends GStructureChooser implements
           queryBuilder.append("pdb_id:")
                   .append(entry.getId().toLowerCase()).append(" OR ");
           isPDBRefsFound = true;
-          // seqRefs.add(entry.getId());
         }
       }
     }
@@ -277,7 +279,8 @@ public class StructureChooser extends GStructureChooser implements
     {
       for (DBRefEntry dbRef : seq.getDBRefs())
       {
-        if (isValidSeqName(getDBRefId(dbRef)))
+        if (isValidSeqName(getDBRefId(dbRef))
+                && queryBuilder.length() < MAX_QLENGHT)
         {
           if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT))
           {
index 7df42fd..4715e48 100644 (file)
@@ -30,10 +30,15 @@ import jalview.structures.models.AAStructureBindingModel;
 import jalview.util.MessageManager;
 
 import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Vector;
 
+import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
 
@@ -76,6 +81,8 @@ public abstract class StructureViewerBase extends GStructureViewer
 
   protected Thread worker = null;
 
+  protected boolean allChainsSelected = false;
+
   /**
    * 
    * @param ap2
@@ -152,6 +159,7 @@ public abstract class StructureViewerBase extends GStructureViewer
     this.ap = alp;
   }
 
+  @Override
   public AlignmentPanel[] getAllAlignmentPanels()
   {
     AlignmentPanel[] t, list = new AlignmentPanel[0];
@@ -291,6 +299,7 @@ public abstract class StructureViewerBase extends GStructureViewer
         // queue.
         new Thread(new Runnable()
         {
+          @Override
           public void run()
           {
             while (worker != null && worker.isAlive() && _started)
@@ -492,4 +501,55 @@ public abstract class StructureViewerBase extends GStructureViewer
     }
     return finished;
   }
+
+  void setChainMenuItems(List<String> chainNames)
+  {
+    chainMenu.removeAll();
+    if (chainNames == null || chainNames.isEmpty())
+    {
+      return;
+    }
+    JMenuItem menuItem = new JMenuItem(
+            MessageManager.getString("label.all"));
+    menuItem.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent evt)
+      {
+        allChainsSelected = true;
+        for (int i = 0; i < chainMenu.getItemCount(); i++)
+        {
+          if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
+          {
+            ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
+          }
+        }
+        showSelectedChains();
+        allChainsSelected = false;
+      }
+    });
+
+    chainMenu.add(menuItem);
+
+    for (String chain : chainNames)
+    {
+      menuItem = new JCheckBoxMenuItem(chain, true);
+      menuItem.addItemListener(new ItemListener()
+      {
+        @Override
+        public void itemStateChanged(ItemEvent evt)
+        {
+          if (!allChainsSelected)
+          {
+            showSelectedChains();
+          }
+        }
+      });
+
+      chainMenu.add(menuItem);
+    }
+  }
+
+  abstract void showSelectedChains();
+
 }
index 817f75c..fd9c584 100644 (file)
  */
 package jalview.io;
 
-import jalview.api.AlignExportSettingI;
-import jalview.api.AlignmentViewPanel;
-import jalview.datamodel.AlignmentExportData;
 import jalview.exceptions.NoFileSelectedException;
-import jalview.gui.IProgressIndicator;
+import jalview.gui.AlignmentPanel;
 import jalview.gui.OOMWarning;
 import jalview.json.binding.biojs.BioJSReleasePojo;
 import jalview.json.binding.biojs.BioJSRepositoryPojo;
@@ -42,15 +39,8 @@ import java.net.URL;
 import java.util.Objects;
 import java.util.TreeMap;
 
-public class BioJsHTMLOutput
+public class BioJsHTMLOutput extends HTMLOutput
 {
-  private AlignmentViewPanel ap;
-
-  private long pSessionId;
-
-  private IProgressIndicator pIndicator;
-
-  private boolean headless;
 
   private static File currentBJSTemplateFile;
 
@@ -67,189 +57,41 @@ public class BioJsHTMLOutput
                   "biojs_template_git_repo",
                   "https://raw.githubusercontent.com/jalview/exporter-templates/master/biojs/package.json");
 
-  public BioJsHTMLOutput(AlignmentViewPanel ap,
-          IProgressIndicator pIndicator)
+  public BioJsHTMLOutput(AlignmentPanel ap)
   {
-    if (ap != null)
-    {
-      this.ap = ap;
-      this.pSessionId = System.currentTimeMillis();
-      this.pIndicator = pIndicator;
-      this.headless = (System.getProperty("java.awt.headless") != null && System
-              .getProperty("java.awt.headless").equals("true"));
-    }
+    super(ap);
   }
 
-  public void exportJalviewAlignmentAsBioJsHtmlFile(String outputFile)
+  @Override
+  public void exportHTML(String outputFile)
   {
-    // String outputFile = null;
+    exportStarted();
     try
     {
       if (outputFile == null)
       {
         outputFile = getOutputFile();
       }
-      AlignExportSettingI exportSettings = new AlignExportSettingI()
-      {
-        @Override
-        public boolean isExportHiddenSequences()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportHiddenColumns()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportAnnotations()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportFeatures()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportGroups()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isCancelled()
-        {
-          return false;
-        }
-
-      };
-      AlignmentExportData exportData = jalview.gui.AlignFrame
-              .getAlignmentForExport(JSONFile.FILE_DESC,
-                      ap.getAlignViewport(), exportSettings);
-      String bioJSON = new FormatAdapter(ap, exportData.getSettings())
-              .formatSequences(JSONFile.FILE_DESC, exportData
-                      .getAlignment(), exportData.getOmitHidden(),
-                      exportData.getStartEndPostions(), ap
-                              .getAlignViewport().getColumnSelection());
-
-      String bioJSTemplateString = getBioJsTemplateAsString();
-      String generatedBioJsWithJalviewAlignmentAsJson = bioJSTemplateString
-              .replaceAll("#sequenceData#", bioJSON).toString();
-
-      PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
-              outputFile));
-      out.print(generatedBioJsWithJalviewAlignmentAsJson);
-      out.flush();
-      out.close();
-      jalview.util.BrowserLauncher.openURL("file:///" + outputFile);
-      if (pIndicator != null && !headless)
-      {
-        pIndicator.setProgressBar(MessageManager.formatMessage(
-                "status.export_complete", "BioJS"), pSessionId);
-      }
-    } catch (NoFileSelectedException ex)
+      generatedFile = new File(outputFile);
+    } catch (NoFileSelectedException e)
     {
-      // do noting if no file was selected
-    } catch (OutOfMemoryError err)
-    {
-      System.out.println("########################\n" + "OUT OF MEMORY "
-              + outputFile + "\n" + "########################");
-      new OOMWarning("Creating Image for " + outputFile, err);
+      setProgressMessage(MessageManager.formatMessage(
+              "status.cancelled_image_export_operation", "BioJS MSA"));
+      return;
     } catch (Exception e)
     {
-      if (pIndicator != null && !headless)
-      {
-      pIndicator.setProgressBar(MessageManager.formatMessage(
-              "info.error_creating_file", "HTML"), pSessionId);
-      }
+      setProgressMessage(MessageManager.formatMessage(
+              "info.error_creating_file", "BioJS MSA"));
       e.printStackTrace();
+      return;
     }
-  }
+    new Thread(this).start();
 
-  public String getOutputFile() throws NoFileSelectedException
-  {
-    String selectedFile = null;
-    if (pIndicator != null && !headless)
-    {
-      pIndicator.setProgressBar(MessageManager.formatMessage(
-              "status.waiting_for_user_to_select_output_file", "HTML"),
-              pSessionId);
-    }
-
-    JalviewFileChooser jvFileChooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
-            new String[] { "html" }, new String[] { "HTML files" },
-            "HTML files");
-    jvFileChooser.setFileView(new JalviewFileView());
-
-    jvFileChooser.setDialogTitle(MessageManager
-            .getString("label.save_as_biojs_html"));
-    jvFileChooser.setToolTipText(MessageManager.getString("action.save"));
-
-    int fileChooserOpt = jvFileChooser.showSaveDialog(null);
-    if (fileChooserOpt == JalviewFileChooser.APPROVE_OPTION)
-    {
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", jvFileChooser
-              .getSelectedFile().getParent());
-      selectedFile = jvFileChooser.getSelectedFile().getPath();
-    }
-    else
-    {
-      pIndicator.setProgressBar(MessageManager.formatMessage(
-              "status.cancelled_image_export_operation", "BioJS"),
-              pSessionId);
-      throw new NoFileSelectedException("No file was selected.");
-    }
-    return selectedFile;
   }
 
-  public static String getBioJsTemplateAsString() throws IOException
-  {
-    InputStreamReader isReader = null;
-    BufferedReader buffReader = null;
-    StringBuilder sb = new StringBuilder();
-    Objects.requireNonNull(getCurrentBJSTemplateFile(),
-            "BioJsTemplate File not initialized!");
-    @SuppressWarnings("deprecation")
-    URL url = getCurrentBJSTemplateFile().toURL();
-    if (url != null)
-    {
-      try
-      {
-        isReader = new InputStreamReader(url.openStream());
-        buffReader = new BufferedReader(isReader);
-        String line;
-        String lineSeparator = System.getProperty("line.separator");
-        while ((line = buffReader.readLine()) != null)
-        {
-          sb.append(line).append(lineSeparator);
-        }
-
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      } finally
-      {
-        if (isReader != null)
-        {
-          isReader.close();
-        }
 
-        if (buffReader != null)
-        {
-          buffReader.close();
-        }
-      }
-    }
-    return sb.toString();
-  }
 
-  public static void refreshBioJSVersionsInfo(String dirName)
+  public static void refreshVersionInfo(String dirName)
           throws URISyntaxException
   {
     File directory = new File(BJS_TEMPLATES_LOCAL_DIRECTORY);
@@ -297,7 +139,7 @@ public class BioJsHTMLOutput
             BioJSRepositoryPojo release = new BioJSRepositoryPojo(
                     gitRepoPkgJson);
             syncUpdates(BJS_TEMPLATES_LOCAL_DIRECTORY, release);
-            refreshBioJSVersionsInfo(BJS_TEMPLATES_LOCAL_DIRECTORY);
+            refreshVersionInfo(BJS_TEMPLATES_LOCAL_DIRECTORY);
           }
         } catch (URISyntaxException e)
         {
@@ -418,4 +260,56 @@ public class BioJsHTMLOutput
     BioJsHTMLOutput.bioJsMSAVersions = bioJsMSAVersions;
   }
 
+  @Override
+  public boolean isEmbedData()
+  {
+    return true;
+  }
+
+  @Override
+  public boolean isLaunchInBrowserAfterExport()
+  {
+    return true;
+  }
+
+  @Override
+  public File getExportedFile()
+  {
+    return generatedFile;
+  }
+
+  @Override
+  public void run()
+  {
+    try
+    {
+      String bioJSON = getBioJSONData();
+      String bioJSTemplateString = HTMLOutput
+              .readFileAsString(getCurrentBJSTemplateFile());
+      String generatedBioJsWithJalviewAlignmentAsJson = bioJSTemplateString
+              .replaceAll("#sequenceData#", bioJSON).toString();
+
+      PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
+              generatedFile));
+      out.print(generatedBioJsWithJalviewAlignmentAsJson);
+      out.flush();
+      out.close();
+      setProgressMessage(MessageManager.formatMessage(
+              "status.export_complete", "BioJS"));
+      exportCompleted();
+
+    } catch (OutOfMemoryError err)
+    {
+      System.out.println("########################\n" + "OUT OF MEMORY "
+              + generatedFile + "\n" + "########################");
+      new OOMWarning("Creating Image for " + generatedFile, err);
+    } catch (Exception e)
+    {
+      setProgressMessage(MessageManager.formatMessage(
+              "info.error_creating_file", "HTML"));
+      e.printStackTrace();
+    }
+
+  }
+
 }
index df0dc06..d58bd67 100755 (executable)
  */
 package jalview.io;
 
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SequenceI;
-import jalview.gui.AlignViewport;
+import jalview.api.AlignExportSettingI;
+import jalview.datamodel.AlignmentExportData;
+import jalview.exceptions.NoFileSelectedException;
 import jalview.gui.AlignmentPanel;
-import jalview.gui.FeatureRenderer;
-import jalview.gui.SequenceRenderer;
+import jalview.gui.IProgressIndicator;
 import jalview.util.MessageManager;
 
-import java.awt.Color;
-import java.awt.Font;
-import java.io.PrintWriter;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Objects;
 
-public class HTMLOutput
+
+public abstract class HTMLOutput implements Runnable
 {
-  AlignViewport av;
+  protected AlignmentPanel ap;
 
-  SequenceRenderer sr;
+  protected long pSessionId;
 
-  jalview.renderer.seqfeatures.FeatureRenderer fr;
+  protected IProgressIndicator pIndicator;
 
-  Color color;
+  protected File generatedFile;
 
-  public HTMLOutput(AlignmentPanel ap, SequenceRenderer sr,
-          FeatureRenderer fr1)
+  public HTMLOutput(AlignmentPanel ap)
   {
-    this.av = ap.av;
-    this.sr = sr;
-
-    fr = new FeatureRenderer(ap);
-    fr.transferSettings(fr1);
-
-    JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
-            new String[] { "html" }, new String[] { "HTML files" },
-            "HTML files");
-
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle(MessageManager.getString("label.save_as_html"));
-    chooser.setToolTipText(MessageManager.getString("action.save"));
-
-    int value = chooser.showSaveDialog(null);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
+    if (ap != null)
     {
-      String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
-              .getSelectedFile().getParent());
-
-      try
-      {
-        PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
-                choice));
-        out.println("<HTML>");
-        out.println("<style type=\"text/css\">");
-        out.println("<!--");
-        out.print("td {font-family: \"" + av.getFont().getFamily()
-                + "\", \"" + av.getFont().getName() + "\", mono; "
-                + "font-size: " + av.getFont().getSize() + "px; ");
-
-        if (av.getFont().getStyle() == Font.BOLD)
-        {
-          out.print("font-weight: BOLD; ");
-        }
-
-        if (av.getFont().getStyle() == Font.ITALIC)
-        {
-          out.print("font-style: italic; ");
-        }
-
-        out.println("text-align: center; }");
-
-        out.println("-->");
-        out.println("</style>");
-        out.println("<BODY>");
-
-        if (av.getWrapAlignment())
-        {
-          drawWrappedAlignment(out);
-        }
-        else
-        {
-          drawUnwrappedAlignment(out);
-        }
-
-        out.println("\n</body>\n</html>");
-        out.close();
-        jalview.util.BrowserLauncher.openURL("file:///" + choice);
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      }
+      this.ap = ap;
+      this.pIndicator = ap.alignFrame;
     }
   }
 
-  void drawUnwrappedAlignment(PrintWriter out)
+  public String getBioJSONData()
   {
-    out.println("<table border=\"1\"><tr><td>\n");
-    out.println("<table border=\"0\"  cellpadding=\"0\" cellspacing=\"0\">\n");
-
-    // ////////////
-    SequenceI seq;
-    AlignmentI alignment = av.getAlignment();
-
-    // draws the top row, the measure rule
-    out.println("<tr><td colspan=\"6\"></td>");
-
-    int i = 0;
+    return getBioJSONData(null);
+  }
 
-    for (i = 10; i < (alignment.getWidth() - 10); i += 10)
+  public String getBioJSONData(AlignExportSettingI exportSettings)
+  {
+    if (!isEmbedData())
     {
-      out.println("<td colspan=\"9\">" + i + "<br>|</td><td></td>");
+      return null;
     }
-
-    out.println("<td colspan=\"3\"></td><td colspan=\"3\">" + i
-            + "<br>|</td>");
-    out.println("</tr>");
-
-    for (i = 0; i < alignment.getHeight(); i++)
+    if (exportSettings == null)
     {
-      seq = alignment.getSequenceAt(i);
-
-      String id = seq.getDisplayId(av.getShowJVSuffix());
-
-      out.println("<tr><td nowrap>" + id + "&nbsp;&nbsp;</td>");
-
-      for (int res = 0; res < seq.getLength(); res++)
+      exportSettings = new AlignExportSettingI()
       {
-        if (!jalview.util.Comparison.isGap(seq.getCharAt(res)))
+        @Override
+        public boolean isExportHiddenSequences()
         {
-          color = sr.getResidueBoxColour(seq, res);
+          return true;
+        }
 
-          color = fr.findFeatureColour(color, seq, res);
+        @Override
+        public boolean isExportHiddenColumns()
+        {
+          return true;
         }
-        else
+
+        @Override
+        public boolean isExportAnnotations()
         {
-          color = Color.white;
+          return true;
         }
 
-        if (color.getRGB() < -1)
+        @Override
+        public boolean isExportFeatures()
         {
-          out.println("<td bgcolor=\"#"
-                  + jalview.util.Format.getHexString(color) + "\">"
-                  + seq.getCharAt(res) + "</td>");
+          return true;
         }
-        else
+
+        @Override
+        public boolean isExportGroups()
         {
-          out.println("<td>" + seq.getCharAt(res) + "</td>");
+          return true;
         }
-      }
 
-      out.println("</tr>");
+        @Override
+        public boolean isCancelled()
+        {
+          return false;
+        }
+      };
     }
-
-    // ////////////
-    out.println("</table>");
-    out.println("</td></tr></table>");
+    AlignmentExportData exportData = jalview.gui.AlignFrame
+            .getAlignmentForExport(JSONFile.FILE_DESC,
+                    ap.getAlignViewport(), exportSettings);
+    String bioJSON = new FormatAdapter(ap, exportData.getSettings())
+            .formatSequences(JSONFile.FILE_DESC, exportData.getAlignment(),
+                    exportData.getOmitHidden(), exportData
+                            .getStartEndPostions(), ap.getAlignViewport()
+                            .getColumnSelection());
+    return bioJSON;
   }
 
-  void drawWrappedAlignment(PrintWriter out)
+  /**
+   * Read a template file content as string
+   * 
+   * @param file
+   *          - the file to be read
+   * @return File content as String
+   * @throws IOException
+   */
+  public static String readFileAsString(File file) throws IOException
   {
-    // //////////////////////////////////
-    // / How many sequences and residues can we fit on a printable page?
-    AlignmentI al = av.getAlignment();
-    SequenceI seq;
-    String r;
-    String g;
-    String b;
-
-    out.println("<table border=\"1\"><tr><td>\n");
-    out.println("<table border=\"0\"  cellpadding=\"0\" cellspacing=\"0\">\n");
-
-    for (int startRes = 0; startRes < al.getWidth(); startRes += av
-            .getWrappedWidth())
+    InputStreamReader isReader = null;
+    BufferedReader buffReader = null;
+    StringBuilder sb = new StringBuilder();
+    Objects.requireNonNull(file, "File must not be null!");
+    @SuppressWarnings("deprecation")
+    URL url = file.toURL();
+    if (url != null)
     {
-      int endRes = startRes + av.getWrappedWidth();
-
-      if (endRes > al.getWidth())
-      {
-        endRes = al.getWidth();
-      }
-
-      if (av.getScaleAboveWrapped())
+      try
       {
-        out.println("<tr>");
-
-        if (av.getScaleLeftWrapped())
-        {
-          out.println("<td colspan=\"7\">&nbsp;</td>");
-        }
-        else
+        isReader = new InputStreamReader(url.openStream());
+        buffReader = new BufferedReader(isReader);
+        String line;
+        String lineSeparator = System.getProperty("line.separator");
+        while ((line = buffReader.readLine()) != null)
         {
-          out.println("<td colspan=\"6\">&nbsp;</td>");
+          sb.append(line).append(lineSeparator);
         }
-
-        for (int i = startRes + 10; i < endRes; i += 10)
-        {
-          out.println("<td colspan=\"9\">" + i + "<br>|</td><td></td>");
-        }
-
-        out.println("</tr>");
-      }
-
-      int startPos, endPos;
-      for (int s = 0; s < al.getHeight(); s++)
+  
+      } catch (Exception ex)
       {
-        out.println("<tr>");
-        seq = al.getSequenceAt(s);
-
-        startPos = seq.findPosition(startRes);
-        endPos = seq.findPosition(endRes) - 1;
-
-        String id = seq.getDisplayId(av.getShowJVSuffix());
-
-        out.println("<td nowrap>" + id + "&nbsp;&nbsp;</td>");
-
-        if (av.getScaleLeftWrapped())
-        {
-          if (startPos > seq.getEnd() || endPos == 0)
-          {
-            out.println("<td nowrap>&nbsp;</td>");
-          }
-          else
-          {
-            out.println("<td nowrap>" + startPos + "&nbsp;&nbsp;</td>");
-          }
-        }
-
-        for (int res = startRes; res < endRes; res++)
-        {
-          if (!jalview.util.Comparison.isGap(seq.getCharAt(res)))
-          {
-            color = sr.getResidueBoxColour(seq, res);
-
-            color = fr.findFeatureColour(color, seq, res);
-          }
-          else
-          {
-            color = Color.white;
-          }
-
-          if (color.getRGB() < -1)
-          {
-            out.println("<td bgcolor=\"#"
-                    + jalview.util.Format.getHexString(color) + "\">"
-                    + seq.getCharAt(res) + "</td>");
-          }
-          else
-          {
-            out.println("<td>" + seq.getCharAt(res) + "</td>");
-          }
-
-        }
-
-        if (av.getScaleRightWrapped()
-                && endRes < startRes + av.getWrappedWidth())
+        ex.printStackTrace();
+      } finally
+      {
+        if (isReader != null)
         {
-          out.println("<td colspan=\""
-                  + (startRes + av.getWrappedWidth() - endRes) + "\">"
-                  + "&nbsp;&nbsp;</td>");
+          isReader.close();
         }
-
-        if (av.getScaleRightWrapped() && startPos < endPos)
+  
+        if (buffReader != null)
         {
-          out.println("<td nowrap>&nbsp;" + endPos + "&nbsp;&nbsp;</td>");
+          buffReader.close();
         }
-
-        out.println("</tr>");
-      }
-
-      if (endRes < al.getWidth())
-      {
-        out.println("<tr><td height=\"5\"></td></tr>");
       }
     }
-
-    out.println("</table>");
-    out.println("</table>");
+    return sb.toString();
   }
 
   public static String getImageMapHTML()
@@ -386,4 +252,122 @@ public class HTMLOutput
                     + "initToolTips(); //--></script>\n");
 
   }
+
+  public String getOutputFile() throws NoFileSelectedException
+  {
+    String selectedFile = null;
+    if (pIndicator != null && !isHeadless())
+    {
+      pIndicator.setProgressBar(MessageManager.formatMessage(
+              "status.waiting_for_user_to_select_output_file", "HTML"),
+              pSessionId);
+    }
+
+    JalviewFileChooser jvFileChooser = new JalviewFileChooser(
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
+            new String[] { "html" }, new String[] { "HTML files" },
+            "HTML files");
+    jvFileChooser.setFileView(new JalviewFileView());
+
+    jvFileChooser.setDialogTitle(MessageManager
+            .getString("label.save_as_html"));
+    jvFileChooser.setToolTipText(MessageManager.getString("action.save"));
+
+    int fileChooserOpt = jvFileChooser.showSaveDialog(null);
+    if (fileChooserOpt == JalviewFileChooser.APPROVE_OPTION)
+    {
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY", jvFileChooser
+              .getSelectedFile().getParent());
+      selectedFile = jvFileChooser.getSelectedFile().getPath();
+    }
+    else
+    {
+      throw new NoFileSelectedException("No file was selected.");
+    }
+    return selectedFile;
+  }
+
+  protected void setProgressMessage(String message)
+  {
+    if (pIndicator != null && !isHeadless())
+    {
+      pIndicator.setProgressBar(message, pSessionId);
+    }
+    else
+    {
+      System.out.println(message);
+    }
+  }
+
+  /**
+   * Answers true if HTML export is invoke in headless mode or false otherwise
+   * 
+   * @return
+   */
+  protected boolean isHeadless()
+  {
+    return System.getProperty("java.awt.headless") != null
+            && System.getProperty("java.awt.headless").equals("true");
+  }
+
+  /**
+   * This method provides implementation of consistent behaviour which should
+   * occur before a HTML file export. It MUST be called at the start of the
+   * exportHTML() method implementation.
+   */
+  protected void exportStarted()
+  {
+    pSessionId = System.currentTimeMillis();
+  }
+
+  /**
+   * This method provides implementation of consistent behaviour which should
+   * occur after a HTML file export. It MUST be called at the end of the
+   * exportHTML() method implementation.
+   */
+  protected void exportCompleted()
+  {
+    if (isLaunchInBrowserAfterExport() && !isHeadless())
+    {
+      try
+      {
+        jalview.util.BrowserLauncher
+                .openURL("file:///" + getExportedFile());
+      } catch (IOException e)
+      {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  /**
+   * if this answers true then BioJSON data will be embedded to the exported
+   * HTML file otherwise it won't be embedded.
+   * 
+   * @return
+   */
+  public abstract boolean isEmbedData();
+
+  /**
+   * if this answers true then the generated HTML file is opened for viewing in
+   * a browser after its generation otherwise it won't be opened in a browser
+   * 
+   * @return
+   */
+  public abstract boolean isLaunchInBrowserAfterExport();
+
+  /**
+   * handle to the generated HTML file
+   * 
+   * @return
+   */
+  public abstract File getExportedFile();
+
+  /**
+   * This is the main method to handle the HTML generation.
+   * 
+   * @param outputFile
+   *          the file path of the generated HTML
+   */
+  public abstract void exportHTML(String outputFile);
 }
index decb06f..1ec3a4e 100644 (file)
  */
 package jalview.io;
 
-import jalview.api.AlignExportSettingI;
-import jalview.api.FeatureRenderer;
-import jalview.datamodel.AlignmentExportData;
-import jalview.datamodel.SequenceI;
-import jalview.gui.AlignViewport;
+import jalview.exceptions.NoFileSelectedException;
 import jalview.gui.AlignmentPanel;
 import jalview.gui.HTMLOptions;
-import jalview.gui.IProgressIndicator;
 import jalview.gui.OOMWarning;
 import jalview.math.AlignmentDimension;
 import jalview.util.MessageManager;
 
-import java.awt.Color;
-import java.awt.FontMetrics;
 import java.awt.Graphics;
-import java.awt.print.Printable;
 import java.awt.print.PrinterException;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 
 import org.jfree.graphics2d.svg.SVGGraphics2D;
 import org.jfree.graphics2d.svg.SVGHints;
 
-public class HtmlSvgOutput
+public class HtmlSvgOutput extends HTMLOutput
 {
-  AlignViewport av;
 
-  FeatureRenderer fr;
 
-  AlignmentPanel ap;
-
-  private IProgressIndicator pIndicator;
-
-  private long pSessionId;
-
-  private boolean headless;
-
-  public HtmlSvgOutput(File file, AlignmentPanel ap)
+  public HtmlSvgOutput(AlignmentPanel ap)
   {
-    this.av = ap.av;
-    this.ap = ap;
-    fr = ap.cloneFeatureRenderer();
-    generateHtmlSvgOutput(file);
+    super(ap);
   }
 
-  public void generateHtmlSvgOutput(File file)
+  @Override
+  public void exportHTML(String outputFile)
   {
-    pIndicator = ap.alignFrame;
-    pSessionId = System.currentTimeMillis();
+    exportStarted();
     try
     {
-      headless = (System.getProperty("java.awt.headless") != null && System
-              .getProperty("java.awt.headless").equals("true"));
-      if (file == null)
+      if (outputFile == null)
       {
-        setProgressMessage(MessageManager.formatMessage(
-                "status.waiting_for_user_to_select_output_file", "HTML"));
-        JalviewFileChooser chooser = getHTMLChooser();
-        chooser.setFileView(new jalview.io.JalviewFileView());
-        chooser.setDialogTitle(ap.alignFrame.getTitle());
-        chooser.setToolTipText(MessageManager.getString("action.save"));
-        int value = chooser.showSaveDialog(ap.alignFrame);
-
-        if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
-        {
-          jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
-                  .getSelectedFile().getParent());
-          file = chooser.getSelectedFile();
-          ap.alignFrame.repaint();
-        }
-        else
-        {
-          setProgressMessage(MessageManager.formatMessage(
-                  "status.cancelled_image_export_operation", "HTML"));
-          return;
-        }
+        outputFile = getOutputFile();
       }
+      generatedFile = new File(outputFile);
+    } catch (NoFileSelectedException e)
+    {
+      setProgressMessage(MessageManager.formatMessage(
+              "status.cancelled_image_export_operation", "HTML"));
+      return;
     } catch (Exception e)
     {
-      pIndicator.setProgressBar(MessageManager.formatMessage(
-              "info.error_creating_file", "HTML"), pSessionId);
+      setProgressMessage(MessageManager.formatMessage(
+              "info.error_creating_file", "HTML"));
       e.printStackTrace();
       return;
     }
-    final File fileX = file;
-    new Thread()
-    {
-      @Override
-      public void run()
-      {
-        try
-        {
-          setProgressMessage(null);
-          setProgressMessage(MessageManager.formatMessage(
-                  "status.exporting_alignment_as_x_file", "HTML"));
-          AlignmentDimension aDimension = ap.getAlignmentDimension();
-          SVGGraphics2D g1 = new SVGGraphics2D(aDimension.getWidth(),
-                  aDimension.getHeight());
-          SVGGraphics2D g2 = new SVGGraphics2D(aDimension.getWidth(),
-                  aDimension.getHeight());
-
-          String renderStyle = jalview.bin.Cache.getDefault(
-                  "HTML_RENDERING", "Prompt each time");
-
-          // If we need to prompt, and if the GUI is visible then
-          // Prompt for rendering style
-          if (renderStyle.equalsIgnoreCase("Prompt each time")
-                  && !(System.getProperty("java.awt.headless") != null && System
-                          .getProperty("java.awt.headless").equals("true")))
-          {
-            HTMLOptions svgOption = new HTMLOptions();
-            renderStyle = svgOption.getValue();
-
-            if (renderStyle == null || svgOption.cancelled)
-            {
-              setProgressMessage(MessageManager.formatMessage(
-                      "status.cancelled_image_export_operation", "HTML"));
-              return;
-            }
-          }
-
-          if (renderStyle.equalsIgnoreCase("Lineart"))
-          {
-            g1.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
-                    SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
-            g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
-                    SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
-          }
-          if (av.getWrapAlignment())
-          {
-            printWrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
-                    g1, g2);
-          }
-          else
-          {
-          printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
-                  g1, g2);
-          }
-
-          String titleSvgData = g1.getSVGDocument();
-          String alignSvgData = g2.getSVGDocument();
-          String jsonData = null;
-          boolean isEmbbedBioJSON = Boolean.valueOf(jalview.bin.Cache
-                  .getDefault("EXPORT_EMBBED_BIOJSON", "true"));
-          if (isEmbbedBioJSON)
-          {
-            AlignExportSettingI exportSettings = new AlignExportSettingI()
-            {
-              @Override
-              public boolean isExportHiddenSequences()
-              {
-                return true;
-              }
-
-              @Override
-              public boolean isExportHiddenColumns()
-              {
-                return true;
-              }
-
-              @Override
-              public boolean isExportAnnotations()
-              {
-                return true;
-              }
-
-              @Override
-              public boolean isExportFeatures()
-              {
-                return true;
-              }
-
-              @Override
-              public boolean isExportGroups()
-              {
-                return true;
-              }
-
-              @Override
-              public boolean isCancelled()
-              {
-                return false;
-              }
-
-            };
-            AlignmentExportData exportData = jalview.gui.AlignFrame
-                    .getAlignmentForExport(JSONFile.FILE_DESC, av,
-                            exportSettings);
-            jsonData = new FormatAdapter(ap, exportData.getSettings())
-                    .formatSequences(JSONFile.FILE_DESC,
-                            exportData.getAlignment(),
-                            exportData.getOmitHidden(),
-                            exportData.getStartEndPostions(),
-                            av.getColumnSelection());
-          }
-          String htmlData = getHtml(titleSvgData, alignSvgData, jsonData,
-                  av.getWrapAlignment());
-          FileOutputStream out = new FileOutputStream(fileX);
-          out.write(htmlData.getBytes());
-          out.flush();
-          out.close();
-          if (!(System.getProperty("java.awt.headless") != null && System
-                  .getProperty("java.awt.headless").equals("true")))
-          {
-            jalview.util.BrowserLauncher.openURL("file:///" + fileX);
-          }
-        } catch (OutOfMemoryError err)
-        {
-          System.out.println("########################\n"
-                  + "OUT OF MEMORY " + fileX + "\n"
-                  + "########################");
-          new OOMWarning("Creating Image for " + fileX, err);
-        } catch (Exception e)
-        {
-          e.printStackTrace();
-          pIndicator.setProgressBar(MessageManager.formatMessage(
-                  "info.error_creating_file", "HTML"), pSessionId);
-        }
-        setProgressMessage(MessageManager.formatMessage(
-                "status.export_complete", "HTML"));
-      }
-    }.start();
-
+    new Thread(this).start();
   }
 
-  private void setProgressMessage(String message)
-  {
-    if (pIndicator != null && !headless)
-    {
-      pIndicator.setProgressBar(message, pSessionId);
-    }
-    else
-    {
-      System.out.println(message);
-    }
-  }
 
   static JalviewFileChooser getHTMLChooser()
   {
@@ -266,141 +81,18 @@ public class HtmlSvgOutput
             "Hypertext Markup Language");
   }
 
-  public int printUnwrapped(int pwidth, int pheight, int pi, Graphics... pg)
+  public int printUnwrapped(int pwidth, int pheight, int pi,
+          Graphics idGraphics, Graphics alignmentGraphics)
           throws PrinterException
   {
-    int idWidth = ap.getVisibleIdWidth(false);
-    FontMetrics fm = ap.getFontMetrics(av.getFont());
-    int scaleHeight = av.getCharHeight() + fm.getDescent();
-
-    pg[0].setColor(Color.white);
-    pg[0].fillRect(0, 0, pwidth, pheight);
-    pg[0].setFont(av.getFont());
-
-    // //////////////////////////////////
-    // / How many sequences and residues can we fit on a printable page?
-    int totalRes = (pwidth - idWidth) / av.getCharWidth();
-    int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1;
-    int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
-
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int startRes;
-
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int endRes;
-
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int startSeq;
-
-    // ///////////////////////////
-    // / Only print these sequences and residues on this page
-    int endSeq;
-    startRes = (pi % pagesWide) * totalRes;
-    endRes = (startRes + totalRes) - 1;
-
-    if (endRes > (av.getAlignment().getWidth() - 1))
-    {
-      endRes = av.getAlignment().getWidth() - 1;
-    }
-    startSeq = (pi / pagesWide) * totalSeq;
-    endSeq = startSeq + totalSeq;
-    if (endSeq > av.getAlignment().getHeight())
-    {
-      endSeq = av.getAlignment().getHeight();
-    }
-    int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
-            * pheight;
-    if (av.isShowAnnotation())
-    {
-      pagesHigh += ap.getAnnotationPanel().adjustPanelHeight() + 3;
-    }
-    pagesHigh /= pheight;
-    if (pi >= (pagesWide * pagesHigh))
-    {
-      return Printable.NO_SUCH_PAGE;
-    }
-
-    // draw Scale
-    pg[1].translate(0, 0);
-    ap.getScalePanel().drawScale(pg[1], startRes, endRes, pwidth - idWidth,
-            scaleHeight);
-    pg[1].translate(-idWidth, scaleHeight);
-
-    // //////////////
-    // Draw the ids
-    Color currentColor = null;
-    Color currentTextColor = null;
-    pg[0].translate(0, scaleHeight);
-    pg[0].setFont(ap.getIdPanel().getIdCanvas().getIdfont());
-    SequenceI seq;
-    for (int i = startSeq; i < endSeq; i++)
-    {
-      seq = av.getAlignment().getSequenceAt(i);
-      if ((av.getSelectionGroup() != null)
-              && av.getSelectionGroup().getSequences(null).contains(seq))
-      {
-        currentColor = Color.gray;
-        currentTextColor = Color.black;
-      }
-      else
-      {
-        currentColor = av.getSequenceColour(seq);
-        currentTextColor = Color.black;
-      }
-      pg[0].setColor(currentColor);
-      pg[0].fillRect(0, (i - startSeq) * av.getCharHeight(), idWidth,
-              av.getCharHeight());
-      pg[0].setColor(currentTextColor);
-      int xPos = 0;
-      if (av.isRightAlignIds())
-      {
-        fm = pg[0].getFontMetrics();
-        xPos = idWidth
-                - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
-                - 4;
-      }
-      pg[0].drawString(seq.getDisplayId(av.getShowJVSuffix()), xPos,
-              (((i - startSeq) * av.getCharHeight()) + av.getCharHeight())
-                      - (av.getCharHeight() / 5));
-    }
-    pg[0].setFont(av.getFont());
-    pg[0].translate(idWidth, 0);
-
-    // draw main sequence panel
-    pg[1].translate(idWidth, 0);
-    ap.getSeqPanel().seqCanvas.drawPanel(pg[1], startRes, endRes, startSeq,
-            endSeq, 0);
-    if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight()))
-    {
-      // draw annotation label - need to offset for current scroll position
-      int offset = -ap.getAlabels().getScrollOffset();
-      pg[0].translate(0, offset);
-      pg[0].translate(-idWidth - 3,
-              (endSeq - startSeq) * av.getCharHeight() + 3);
-      ap.getAlabels().drawComponent(pg[0], idWidth);
-      pg[0].translate(idWidth + 3, 0);
-      pg[0].translate(0, -offset);
-
-      // draw annotation - need to offset for current scroll position
-      pg[1].translate(0, offset);
-      pg[1].translate(-idWidth - 3,
-              (endSeq - startSeq) * av.getCharHeight() + 3);
-      pg[1].translate(idWidth + 3, 0);
-      ap.getAnnotationPanel().renderer.drawComponent(
-              ap.getAnnotationPanel(), av, pg[1], -1, startRes, endRes + 1);
-      pg[1].translate(0, -offset);
-    }
-
-    return Printable.PAGE_EXISTS;
+    return ap.printUnwrapped(pwidth, pheight, pi, idGraphics,
+            alignmentGraphics);
   }
 
   public int printWrapped(int pwidth, int pheight, int pi, Graphics... pg)
           throws PrinterException
   {
-    return ap.printWrappedAlignment(pg[1], pwidth, pheight, pi);
+    return ap.printWrappedAlignment(pwidth, pheight, pi, pg[0]);
   }
 
   private String getHtml(String titleSvg, String alignmentSvg,
@@ -474,11 +166,9 @@ public class HtmlSvgOutput
               .append(alignmentSvg).append("</div>");
       htmlSvg.append("<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
               + "<script language=\"JavaScript\" type=\"text/javascript\"  src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n");
-
     }
 
     // javascript for launching file in Jalview
-
     htmlSvg.append("<script language=\"JavaScript\">\n");
     htmlSvg.append("function openJalviewUsingCurrentUrl(){\n");
     htmlSvg.append("    var json = JSON.parse(document.getElementById(\"seqData\").innerHTML);\n");
@@ -503,269 +193,115 @@ public class HtmlSvgOutput
     htmlSvg.append("    document.body.removeChild(myForm);\n");
     htmlSvg.append("}\n");
 
-    // jquery facebox for displaying raw BioJSON data");
     if (jsonData != null)
     {
-      htmlSvg.append("/* Facebox (for jQuery)\n");
-      htmlSvg.append("* version: 1.3\n");
-      htmlSvg.append(" * @requires jQuery v1.2 or later\n");
-      htmlSvg.append(" * @homepage https://github.com/defunkt/facebox\n");
-      htmlSvg.append(" * Licensed under the MIT:\n");
-      htmlSvg.append(" *   http://www.opensource.org/licenses/mit-license.php\n");
-      htmlSvg.append(" * Copyright Forever Chris Wanstrath, Kyle Neath\n");
-      htmlSvg.append(" * Usage:\n");
-      htmlSvg.append(" *  jQuery(document).ready(function() {\n");
-      htmlSvg.append(" *    jQuery('a[rel*=facebox]').facebox()\n");
-      htmlSvg.append(" *  })\n");
-      htmlSvg.append(" *  <a href=\"#terms\" rel=\"facebox\">Terms</a>\n");
-      htmlSvg.append(" *    Loads the #terms div in the box\n");
-      htmlSvg.append(" *  <a href=\"terms.html\" rel=\"facebox\">Terms</a>\n");
-      htmlSvg.append(" *    Loads the terms.html page in the box\n");
-      htmlSvg.append(" *  <a href=\"terms.png\" rel=\"facebox\">Terms</a>\n");
-      htmlSvg.append(" *    Loads the terms.png image in the box\n");
-      htmlSvg.append(" *  You can also use it programmatically:\n");
-      htmlSvg.append(" *    jQuery.facebox('some html')\n");
-      htmlSvg.append(" *    jQuery.facebox('some html', 'my-groovy-style')\n");
-      htmlSvg.append(" *  The above will open a facebox with \"some html\" as the content.\n");
-      htmlSvg.append(" *    jQuery.facebox(function($) {\n");
-      htmlSvg.append(" *      $.get('blah.html', function(data) { $.facebox(data) })\n");
-      htmlSvg.append(" *    })\n");
-      htmlSvg.append(" *  The above will show a loading screen before the passed function is called,\n");
-      htmlSvg.append(" *  allowing for a better ajaxy experience.\n");
-      htmlSvg.append(" *  The facebox function can also display an ajax page, an image, or the contents of a div:\n");
-      htmlSvg.append(" *    jQuery.facebox({ ajax: 'remote.html' })\n");
-      htmlSvg.append(" *    jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style')\n");
-      htmlSvg.append(" *    jQuery.facebox({ image: 'stairs.jpg' })\n");
-      htmlSvg.append(" *    jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style')\n");
-      htmlSvg.append(" *    jQuery.facebox({ div: '#box' })\n");
-      htmlSvg.append(" *    jQuery.facebox({ div: '#box' }, 'my-groovy-style')\n");
-      htmlSvg.append(" *    Want to close the facebox?  Trigger the 'close.facebox' document event:\n");
-      htmlSvg.append(" *    jQuery(document).trigger('close.facebox')\n");
-      htmlSvg.append(" *  Facebox also has a bunch of other hooks:\n");
-      htmlSvg.append(" *    loading.facebox\n");
-      htmlSvg.append(" *    beforeReveal.facebox\n");
-      htmlSvg.append(" *    reveal.facebox (aliased as 'afterReveal.facebox')\n");
-      htmlSvg.append(" *    init.facebox\n");
-      htmlSvg.append(" *    afterClose.facebox\n");
-      htmlSvg.append(" *  Simply bind a function to any of these hooks:\n");
-      htmlSvg.append(" *   $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })\n");
-      htmlSvg.append(" *\n");
-      htmlSvg.append(" */\n");
-      htmlSvg.append("(function($) {\n");
-      htmlSvg.append("  $.facebox = function(data, klass) {\n");
-      htmlSvg.append("    $.facebox.loading()\n");
-      htmlSvg.append("    if (data.ajax) fillFaceboxFromAjax(data.ajax, klass)\n");
-      htmlSvg.append("    else if (data.image) fillFaceboxFromImage(data.image, klass)\n");
-      htmlSvg.append("    else if (data.div) fillFaceboxFromHref(data.div, klass)\n");
-      htmlSvg.append("    else if ($.isFunction(data)) data.call($)\n");
-      htmlSvg.append("    else $.facebox.reveal(data, klass)\n");
-      htmlSvg.append("  }\n");
-
-      htmlSvg.append("  $.extend($.facebox, {\n");
-      htmlSvg.append("    settings: {\n");
-      htmlSvg.append("      opacity      : 0.2,\n");
-      htmlSvg.append("      overlay      : true,\n");
-      htmlSvg.append("      loadingImage : 'https://raw.githubusercontent.com/jalview/biojson/gh-pages/images/loading.gif',\n");
-      htmlSvg.append("      closeImage   : 'https://raw.githubusercontent.com/jalview/biojson/gh-pages/images/cancel.png',\n");
-      htmlSvg.append("      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],\n");
-      htmlSvg.append("      faceboxHtml  : '<div  id=\"facebox\" style=\"display:none; width: 95%; height: 85%; overflow: auto;\"> ");
-      htmlSvg.append("      <div class=\"popup\"> ");
-      htmlSvg.append("        <div class=\"content\"> ");
-      htmlSvg.append("        </div> ");
-      htmlSvg.append("        <a href=\"#\" class=\"close\"></a> ");
-      htmlSvg.append("      </div> ");
-      htmlSvg.append("    </div>'\n");
-      htmlSvg.append("    },      \n");
-      htmlSvg.append("    loading: function() {\n");
-      htmlSvg.append("      init()\n");
-      htmlSvg.append("      if ($('#facebox .loading').length == 1) return true\n");
-      htmlSvg.append("      showOverlay()      \n");
-      htmlSvg.append("      $('#facebox .content').empty().\n");
-      htmlSvg.append("        append('<div class=\"loading\"><img src=\"'+$.facebox.settings.loadingImage+'\"/></div>')\n");
-      htmlSvg.append("      $('#facebox').show().css({\n");
-      htmlSvg.append("        top:    getPageScroll()[1] + (getPageHeight() / 10),\n");
-      htmlSvg.append("        left:    $(window).width() / 2 - ($('#facebox .popup').outerWidth() / 2)\n");
-      htmlSvg.append("      })      \n");
-      htmlSvg.append("      $(document).bind('keydown.facebox', function(e) {\n");
-      htmlSvg.append("       if (e.keyCode == 27) $.facebox.close()\n");
-      htmlSvg.append("        return true\n");
-      htmlSvg.append("      })\n");
-      htmlSvg.append("      $(document).trigger('loading.facebox')\n");
-      htmlSvg.append("    },\n");
-      htmlSvg.append("    reveal: function(data, klass) {\n");
-      htmlSvg.append("      $(document).trigger('beforeReveal.facebox')\n");
-      htmlSvg.append("      if (klass) $('#facebox .content').addClass(klass)\n");
-      htmlSvg.append("      $('#facebox .content').empty().append('<pre><code>'+JSON.stringify(JSON.parse(data),null,4)+'</pre></code>')\n");
-      htmlSvg.append("      $('#facebox .popup').children().fadeIn('normal')\n");
-      htmlSvg.append("      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').outerWidth() / 2))\n");
-      htmlSvg.append("      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')\n");
-      htmlSvg.append("    },      \n");
-      htmlSvg.append("    close: function() {\n");
-      htmlSvg.append("      $(document).trigger('close.facebox')\n");
-      htmlSvg.append("      return false\n");
-      htmlSvg.append("    }\n");
-      htmlSvg.append("  })\n");
-      htmlSvg.append("  $.fn.facebox = function(settings) {\n");
-      htmlSvg.append("    if ($(this).length == 0) return    \n");
-      htmlSvg.append("    init(settings)      \n");
-      htmlSvg.append("    function clickHandler() {\n");
-      htmlSvg.append("      $.facebox.loading(true)      \n");
-      htmlSvg.append("      // support for rel=\"facebox.inline_popup\" syntax, to add a class\n");
-      htmlSvg.append("      // also supports deprecated \"facebox[.inline_popup]\" syntax\n");
-      htmlSvg.append("      var klass = this.rel.match(/facebox\\[?\\.(\\w+)\\]?/)\n");
-      htmlSvg.append("      if (klass) klass = klass[1]\n");
-      htmlSvg.append("      fillFaceboxFromHref(this.href, klass)\n");
-      htmlSvg.append("      return false\n");
-      htmlSvg.append("    }      \n");
-      htmlSvg.append("    return this.bind('click.facebox', clickHandler)\n");
-      htmlSvg.append("  }\n");
-      htmlSvg.append("  // called one time to setup facebox on this page\n");
-      htmlSvg.append("  function init(settings) {\n");
-      htmlSvg.append("    if ($.facebox.settings.inited) return true\n");
-      htmlSvg.append("    else $.facebox.settings.inited = true\n");
-      htmlSvg.append("    $(document).trigger('init.facebox')\n");
-      htmlSvg.append("    makeCompatible()\n");
-      htmlSvg.append("    var imageTypes = $.facebox.settings.imageTypes.join('|')\n");
-      htmlSvg.append("    $.facebox.settings.imageTypesRegexp = new RegExp('\\\\.(' + imageTypes + ')(\\\\?.*)?$', 'i')\n");
-
-      htmlSvg.append("    if (settings) $.extend($.facebox.settings, settings)\n");
-      htmlSvg.append("    $('body').append($.facebox.settings.faceboxHtml)\n");
-
-      htmlSvg.append("    var preload = [ new Image(), new Image() ]\n");
-      htmlSvg.append("    preload[0].src = $.facebox.settings.closeImage\n");
-      htmlSvg.append("    preload[1].src = $.facebox.settings.loadingImage\n");
-
-      htmlSvg.append("    $('#facebox').find('.b:first, .bl').each(function() {\n");
-      htmlSvg.append("      preload.push(new Image())\n");
-      htmlSvg.append("      preload.slice(-1).src = $(this).css('background-image').replace(/url\\((.+)\\)/, '$1')\n");
-      htmlSvg.append("    })\n");
-
-      htmlSvg.append("    $('#facebox .close')\n");
-      htmlSvg.append("      .click($.facebox.close)\n");
-      htmlSvg.append("      .append('<img src=\"'\n");
-      htmlSvg.append("              + $.facebox.settings.closeImage\n");
-      htmlSvg.append("              + '\" class=\"close_image\" title=\"close\">')\n");
-      htmlSvg.append("  }\n");
-
-      htmlSvg.append("  // getPageScroll() by quirksmode.com\n");
-      htmlSvg.append("  function getPageScroll() {\n");
-      htmlSvg.append("    var xScroll, yScroll;\n");
-      htmlSvg.append("    if (self.pageYOffset) {\n");
-      htmlSvg.append("      yScroll = self.pageYOffset;\n");
-      htmlSvg.append("      xScroll = self.pageXOffset;\n");
-      htmlSvg.append("    } else if (document.documentElement && document.documentElement.scrollTop) {     // Explorer 6 Strict\n");
-      htmlSvg.append("      yScroll = document.documentElement.scrollTop;\n");
-      htmlSvg.append("      xScroll = document.documentElement.scrollLeft;\n");
-      htmlSvg.append("    } else if (document.body) {// all other Explorers\n");
-      htmlSvg.append("      yScroll = document.body.scrollTop;\n");
-      htmlSvg.append("      xScroll = document.body.scrollLeft;\n");
-      htmlSvg.append("    }\n");
-      htmlSvg.append("    return new Array(xScroll,yScroll)\n");
-      htmlSvg.append("  }\n");
-
-      // Adapted from getPageSize() by quirksmode.com");
-      htmlSvg.append("  function getPageHeight() {\n");
-      htmlSvg.append("    var windowHeight\n");
-      htmlSvg.append("    if (self.innerHeight) {    // all except Explorer\n");
-      htmlSvg.append("      windowHeight = self.innerHeight;\n");
-      htmlSvg.append("    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode\n");
-      htmlSvg.append("      windowHeight = document.documentElement.clientHeight;\n");
-      htmlSvg.append("    } else if (document.body) { // other Explorers\n");
-      htmlSvg.append("      windowHeight = document.body.clientHeight;\n");
-      htmlSvg.append("    }\n");
-      htmlSvg.append("    return windowHeight\n");
-      htmlSvg.append("  }\n");
-
-      htmlSvg.append("  // Backwards compatibility\n");
-      htmlSvg.append("  function makeCompatible() {\n");
-      htmlSvg.append("    var $s = $.facebox.settings      \n");
-      htmlSvg.append("    $s.loadingImage = $s.loading_image || $s.loadingImage\n");
-      htmlSvg.append("    $s.closeImage = $s.close_image || $s.closeImage\n");
-      htmlSvg.append("    $s.imageTypes = $s.image_types || $s.imageTypes\n");
-      htmlSvg.append("    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml\n");
-      htmlSvg.append("  }\n");
-
-      htmlSvg.append("  // Figures out what you want to display and displays it\n");
-      htmlSvg.append("  // formats are:\n");
-      htmlSvg.append("  //     div: #id\n");
-      htmlSvg.append("  //   image: blah.extension\n");
-      htmlSvg.append("  //    ajax: anything else\n");
-      htmlSvg.append("  function fillFaceboxFromHref(href, klass) {\n");
-      htmlSvg.append("    // div\n");
-      htmlSvg.append("    if (href.match(/#/)) {\n");
-      htmlSvg.append("      var url    = window.location.href.split('#')[0]\n");
-      htmlSvg.append("      var target = href.replace(url,'')\n");
-      htmlSvg.append("      if (target == '#') return\n");
-      htmlSvg.append("      $.facebox.reveal($(target).html(), klass)\n");
-
-      htmlSvg.append("    // image\n");
-      htmlSvg.append("    } else if (href.match($.facebox.settings.imageTypesRegexp)) {\n");
-      htmlSvg.append("      fillFaceboxFromImage(href, klass)\n");
-      htmlSvg.append("    // ajax\n");
-      htmlSvg.append("    } else {\n");
-      htmlSvg.append("      fillFaceboxFromAjax(href, klass)\n");
-      htmlSvg.append("    }\n");
-      htmlSvg.append("  }\n");
-
-      htmlSvg.append("  function fillFaceboxFromImage(href, klass) {\n");
-      htmlSvg.append("    var image = new Image()\n");
-      htmlSvg.append("    image.onload = function() {\n");
-      htmlSvg.append("      $.facebox.reveal('<div class=\"image\"><img src=\"' + image.src + '\" /></div>', klass)\n");
-      htmlSvg.append("    }\n");
-      htmlSvg.append("    image.src = href\n");
-      htmlSvg.append("   }\n");
-
-      htmlSvg.append("  function fillFaceboxFromAjax(href, klass) {\n");
-      htmlSvg.append("    $.facebox.jqxhr = $.get(href, function(data) { $.facebox.reveal(data, klass) })\n");
-      htmlSvg.append("  }\n");
+      // JQuery FaceBox for displaying raw BioJSON data");
+      File faceBoxJsFile = new File("examples/javascript/facebox-1.3.js");
+      try
+      {
+        htmlSvg.append(HTMLOutput.readFileAsString(faceBoxJsFile));
+      } catch (IOException e)
+      {
+        e.printStackTrace();
+      }
+    }
 
-      htmlSvg.append("  function skipOverlay() {\n");
-      htmlSvg.append("    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null\n");
-      htmlSvg.append("  }\n");
+    htmlSvg.append("</script>\n");
+    htmlSvg.append("</html>");
+    return htmlSvg.toString();
+  }
 
-      htmlSvg.append("  function showOverlay() {\n");
-      htmlSvg.append("    if (skipOverlay()) return\n");
+  @Override
+  public boolean isEmbedData()
+  {
+    return Boolean.valueOf(jalview.bin.Cache.getDefault(
+            "EXPORT_EMBBED_BIOJSON", "true"));
+  }
 
-      htmlSvg.append("    if ($('#facebox_overlay').length == 0)\n");
-      htmlSvg.append("      $(\"body\").append('<div id=\"facebox_overlay\" class=\"facebox_hide\"></div>')\n");
+  @Override
+  public boolean isLaunchInBrowserAfterExport()
+  {
+    return true;
+  }
 
-      htmlSvg.append("    $('#facebox_overlay').hide().addClass(\"facebox_overlayBG\")\n");
-      htmlSvg.append("      .css('opacity', $.facebox.settings.opacity)\n");
-      htmlSvg.append("      .click(function() { $(document).trigger('close.facebox') })\n");
-      htmlSvg.append("       .fadeIn(200)\n");
-      htmlSvg.append("    return false\n");
-      htmlSvg.append("  }\n");
+  @Override
+  public File getExportedFile()
+  {
+    return generatedFile;
+  }
 
-      htmlSvg.append("  function hideOverlay() {\n");
-      htmlSvg.append("    if (skipOverlay()) return      \n");
-      htmlSvg.append("    $('#facebox_overlay').fadeOut(200, function(){\n");
-      htmlSvg.append("      $(\"#facebox_overlay\").removeClass(\"facebox_overlayBG\")\n");
-      htmlSvg.append("      $(\"#facebox_overlay\").addClass(\"facebox_hide\")\n");
-      htmlSvg.append("      $(\"#facebox_overlay\").remove()\n");
-      htmlSvg.append("    })      \n");
-      htmlSvg.append("    return false\n");
-      htmlSvg.append("  }\n");
+  @Override
+  public void run()
+  {
+    try
+    {
+      setProgressMessage(null);
+      setProgressMessage(MessageManager.formatMessage(
+              "status.exporting_alignment_as_x_file", "HTML"));
+      AlignmentDimension aDimension = ap.getAlignmentDimension();
+      SVGGraphics2D idPanelGraphics = new SVGGraphics2D(
+              aDimension.getWidth(), aDimension.getHeight());
+      SVGGraphics2D alignPanelGraphics = new SVGGraphics2D(
+              aDimension.getWidth(), aDimension.getHeight());
+
+      String renderStyle = jalview.bin.Cache.getDefault("HTML_RENDERING",
+              "Prompt each time");
+
+      // If we need to prompt, and if the GUI is visible then
+      // Prompt for rendering style
+      if (renderStyle.equalsIgnoreCase("Prompt each time") && !isHeadless())
+      {
+        HTMLOptions svgOption = new HTMLOptions();
+        renderStyle = svgOption.getValue();
 
-      htmlSvg.append("  $(document).bind('close.facebox', function() {\n");
-      htmlSvg.append("    if ($.facebox.jqxhr) {\n");
-      htmlSvg.append("      $.facebox.jqxhr.abort()\n");
-      htmlSvg.append("      $.facebox.jqxhr = null\n");
-      htmlSvg.append("    }\n");
-      htmlSvg.append("    $(document).unbind('keydown.facebox')\n");
-      htmlSvg.append("    $('#facebox').fadeOut(function() {\n");
-      htmlSvg.append("      $('#facebox .content').removeClass().addClass('content')\n");
-      htmlSvg.append("      $('#facebox .loading').remove()\n");
-      htmlSvg.append("      $(document).trigger('afterClose.facebox')\n");
-      htmlSvg.append("    })\n");
-      htmlSvg.append("    hideOverlay()\n");
-      htmlSvg.append("  })\n");
+        if (renderStyle == null || svgOption.cancelled)
+        {
+          setProgressMessage(MessageManager.formatMessage(
+                  "status.cancelled_image_export_operation", "HTML"));
+          return;
+        }
+      }
 
-      htmlSvg.append("})(jQuery);\n");
+      if (renderStyle.equalsIgnoreCase("Lineart"))
+      {
+        idPanelGraphics.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+                SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
+        alignPanelGraphics.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+                SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
+      }
+      if (ap.av.getWrapAlignment())
+      {
+        printWrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
+                alignPanelGraphics);
+      }
+      else
+      {
+        printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
+                idPanelGraphics, alignPanelGraphics);
+      }
 
+      String idPanelSvgData = idPanelGraphics.getSVGDocument();
+      String alignPanelSvgData = alignPanelGraphics.getSVGDocument();
+      String jsonData = getBioJSONData();
+      String htmlData = getHtml(idPanelSvgData, alignPanelSvgData,
+              jsonData, ap.av.getWrapAlignment());
+      FileOutputStream out = new FileOutputStream(generatedFile);
+      out.write(htmlData.getBytes());
+      out.flush();
+      out.close();
+      setProgressMessage(MessageManager.formatMessage(
+              "status.export_complete", "HTML"));
+      exportCompleted();
+    } catch (OutOfMemoryError err)
+    {
+      System.out.println("########################\n" + "OUT OF MEMORY "
+              + generatedFile + "\n" + "########################");
+      new OOMWarning("Creating Image for " + generatedFile, err);
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+      setProgressMessage(MessageManager.formatMessage(
+              "info.error_creating_file", "HTML"));
     }
-
-    htmlSvg.append("</script>\n");
-    htmlSvg.append("</html>");
-    return htmlSvg.toString();
   }
 }
index d5593e3..3feae5d 100755 (executable)
@@ -192,13 +192,13 @@ public class JnetAnnotationMaker
           if (id.equals("JNETCONF"))
           {
             annot = new AlignmentAnnotation(preds[i].getName(),
-                    "JNet Output", annotations, 0f, 10f,
+                    "JPred Output", annotations, 0f, 10f,
                     AlignmentAnnotation.BAR_GRAPH);
           }
           else
           {
             annot = new AlignmentAnnotation(preds[i].getName(),
-                    "JNet Output", annotations);
+                    "JPred Output", annotations);
           }
 
           if (seqRef != null)
index 89f1068..6c8f40f 100644 (file)
 package jalview.io;
 
 import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.io.gff.GffConstants;
+import jalview.util.MessageManager;
 import jalview.util.UrlLink;
 
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -39,8 +42,69 @@ import java.util.Map;
  */
 public class SequenceAnnotationReport
 {
+  private static final String COMMA = ",";
+
+  private static final String ELLIPSIS = "...";
+
+  private static final int MAX_REFS_PER_SOURCE = 4;
+
+  private static final int MAX_SOURCES = 40;
+
+  private static final String[][] PRIMARY_SOURCES = new String[][] {
+      DBRefSource.CODINGDBS, DBRefSource.DNACODINGDBS,
+      DBRefSource.PROTEINDBS };
+
   final String linkImageURL;
 
+  /*
+   * Comparator to order DBRefEntry by Source + accession id (case-insensitive)
+   */
+  private static Comparator<DBRefEntry> comparator = new Comparator<DBRefEntry>()
+  {
+
+    @Override
+    public int compare(DBRefEntry ref1, DBRefEntry ref2)
+    {
+      String s1 = ref1.getSource();
+      String s2 = ref2.getSource();
+      boolean s1Primary = isPrimarySource(s1);
+      boolean s2Primary = isPrimarySource(s2);
+      if (s1Primary && !s2Primary)
+      {
+        return -1;
+      }
+      if (!s1Primary && s2Primary)
+      {
+        return 1;
+      }
+      int comp = s1 == null ? -1 : (s2 == null ? 1 : s1
+              .compareToIgnoreCase(s2));
+      if (comp == 0)
+      {
+        String a1 = ref1.getAccessionId();
+        String a2 = ref2.getAccessionId();
+        comp = a1 == null ? -1 : (a2 == null ? 1 : a1
+                .compareToIgnoreCase(a2));
+      }
+      return comp;
+    }
+
+    private boolean isPrimarySource(String source)
+    {
+      for (String[] primary : PRIMARY_SOURCES)
+      {
+        for (String s : primary)
+        {
+          if (source.equals(s))
+          {
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+  };
+
   public SequenceAnnotationReport(String linkImageURL)
   {
     this.linkImageURL = linkImageURL;
@@ -49,37 +113,35 @@ public class SequenceAnnotationReport
   /**
    * Append text for the list of features to the tooltip
    * 
-   * @param tooltipText2
+   * @param sb
    * @param rpos
    * @param features
    * @param minmax
    */
-  public void appendFeatures(final StringBuffer tooltipText2, int rpos,
+  public void appendFeatures(final StringBuilder sb, int rpos,
           List<SequenceFeature> features, Map<String, float[][]> minmax)
   {
     if (features != null)
     {
       for (SequenceFeature feature : features)
       {
-        appendFeature(tooltipText2, rpos, minmax, feature);
+        appendFeature(sb, rpos, minmax, feature);
       }
     }
   }
 
   /**
-   * Appends text for one sequence feature to the string buffer
+   * Appends the feature at rpos to the given buffer
    * 
    * @param sb
    * @param rpos
    * @param minmax
-   *          {{min, max}, {min, max}} positional and non-positional feature
-   *          scores for this type
    * @param feature
    */
-  void appendFeature(final StringBuffer sb, int rpos,
+  void appendFeature(final StringBuilder sb, int rpos,
           Map<String, float[][]> minmax, SequenceFeature feature)
   {
-    if ("disulfide bond".equals(feature.getType()))
+    if (feature.isContactFeature())
     {
       if (feature.getBegin() == rpos || feature.getEnd() == rpos)
       {
@@ -87,7 +149,8 @@ public class SequenceAnnotationReport
         {
           sb.append("<br>");
         }
-        sb.append("disulfide bond ").append(feature.getBegin()).append(":")
+        sb.append(feature.getType()).append(" ").append(feature.getBegin())
+                .append(":")
                 .append(feature.getEnd());
       }
     }
@@ -109,7 +172,7 @@ public class SequenceAnnotationReport
         }
         if (feature.begin != feature.end)
         {
-          sb.append(" " + feature.end);
+          sb.append(" ").append(feature.end);
         }
 
         if (feature.getDescription() != null
@@ -117,13 +180,12 @@ public class SequenceAnnotationReport
         {
           String tmpString = feature.getDescription();
           String tmp2up = tmpString.toUpperCase();
-          final int startTag = tmp2up.indexOf("<HTML>");
+          int startTag = tmp2up.indexOf("<HTML>");
           if (startTag > -1)
           {
             tmpString = tmpString.substring(startTag + 6);
             tmp2up = tmp2up.substring(startTag + 6);
           }
-          // TODO strips off </body> but not <body> - is that intended?
           int endTag = tmp2up.indexOf("</BODY>");
           if (endTag > -1)
           {
@@ -148,7 +210,9 @@ public class SequenceAnnotationReport
               // be used, so we must remove < > symbols
               tmpString = tmpString.replaceAll("<", "&lt;");
               tmpString = tmpString.replaceAll(">", "&gt;");
-              sb.append("; ").append(tmpString);
+
+              sb.append("; ");
+              sb.append(tmpString);
             }
             else
             {
@@ -156,11 +220,7 @@ public class SequenceAnnotationReport
             }
           }
         }
-
-        /*
-         * score should be shown if there is one, and min != max
-         * for this feature type (e.g. not all 0)
-         */
+        // check score should be shown
         if (!Float.isNaN(feature.getScore()))
         {
           float[][] rng = (minmax == null) ? null : minmax.get(feature
@@ -183,7 +243,6 @@ public class SequenceAnnotationReport
         }
       }
     }
-    appendLinks(sb, feature);
   }
 
   /**
@@ -254,26 +313,42 @@ public class SequenceAnnotationReport
     return urlSets.values();
   }
 
-  public void createSequenceAnnotationReport(final StringBuffer tip,
+  public void createSequenceAnnotationReport(final StringBuilder tip,
           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
           Map<String, float[][]> minmax)
   {
     createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats,
-            true, minmax);
+            minmax, false);
   }
 
-  public void createSequenceAnnotationReport(final StringBuffer tip,
+  /**
+   * Builds an html formatted report of sequence details and appends it to the
+   * provided buffer.
+   * 
+   * @param sb
+   *          buffer to append report to
+   * @param sequence
+   *          the sequence the report is for
+   * @param showDbRefs
+   *          whether to include database references for the sequence
+   * @param showNpFeats
+   *          whether to include non-positional sequence features
+   * @param minmax
+   * @param summary
+   * @return
+   */
+  int createSequenceAnnotationReport(final StringBuilder sb,
           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
-          boolean tableWrap, Map<String, float[][]> minmax)
+          Map<String, float[][]> minmax, boolean summary)
   {
     String tmp;
-    tip.append("<i>");
+    sb.append("<i>");
 
     int maxWidth = 0;
     if (sequence.getDescription() != null)
     {
       tmp = sequence.getDescription();
-      tip.append("<br>" + tmp);
+      sb.append("<br>").append(tmp);
       maxWidth = Math.max(maxWidth, tmp.length());
     }
     SequenceI ds = sequence;
@@ -284,16 +359,81 @@ public class SequenceAnnotationReport
     DBRefEntry[] dbrefs = ds.getDBRefs();
     if (showDbRefs && dbrefs != null)
     {
-      for (int i = 0; i < dbrefs.length; i++)
+      // note this sorts the refs held on the sequence!
+      Arrays.sort(dbrefs, comparator);
+      boolean ellipsis = false;
+      String source = null;
+      String lastSource = null;
+      int countForSource = 0;
+      int sourceCount = 0;
+      boolean moreSources = false;
+      int lineLength = 0;
+
+      for (DBRefEntry ref : dbrefs)
+      {
+        source = ref.getSource();
+        if (source == null)
+        {
+          // shouldn't happen
+          continue;
+        }
+        boolean sourceChanged = !source.equals(lastSource);
+        if (sourceChanged)
+        {
+          lineLength = 0;
+          countForSource = 0;
+          sourceCount++;
+        }
+        if (sourceCount > MAX_SOURCES && summary)
+        {
+          ellipsis = true;
+          moreSources = true;
+          break;
+        }
+        lastSource = source;
+        countForSource++;
+        if (countForSource == 1 || !summary)
+        {
+          sb.append("<br>");
+        }
+        if (countForSource <= MAX_REFS_PER_SOURCE || !summary)
+        {
+          String accessionId = ref.getAccessionId();
+          lineLength += accessionId.length() + 1;
+          if (countForSource > 1 && summary)
+          {
+            sb.append(", ").append(accessionId);
+            lineLength++;
+          }
+          else
+          {
+            sb.append(source).append(" ").append(accessionId);
+            lineLength += source.length();
+          }
+          maxWidth = Math.max(maxWidth, lineLength);
+        }
+        if (countForSource == MAX_REFS_PER_SOURCE && summary)
+        {
+          sb.append(COMMA).append(ELLIPSIS);
+          ellipsis = true;
+        }
+      }
+      if (moreSources)
       {
-        tip.append("<br>");
-        tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
-        tip.append(tmp);
-        maxWidth = Math.max(maxWidth, tmp.length());
+        sb.append("<br>").append(ELLIPSIS).append(COMMA).append(source)
+                .append(COMMA).append(ELLIPSIS);
+      }
+      if (ellipsis)
+      {
+        sb.append("<br>(");
+        sb.append(MessageManager.getString("label.output_seq_details"));
+        sb.append(")");
       }
     }
 
-    // ADD NON POSITIONAL SEQUENCE INFO
+    /*
+     * add non-positional features if wanted
+     */
     SequenceFeature[] features = sequence.getSequenceFeatures();
     if (showNpFeats && features != null)
     {
@@ -301,21 +441,29 @@ public class SequenceAnnotationReport
       {
         if (features[i].begin == 0 && features[i].end == 0)
         {
-          int sz = -tip.length();
-          List<SequenceFeature> tfeat = new ArrayList<SequenceFeature>();
-          tfeat.add(features[i]);
-          appendFeatures(tip, 0, tfeat, minmax);
-          sz += tip.length();
+          int sz = -sb.length();
+          appendFeature(sb, 0, minmax, features[i]);
+          sz += sb.length();
           maxWidth = Math.max(maxWidth, sz);
         }
       }
     }
+    sb.append("</i>");
+    return maxWidth;
+  }
+
+  public void createTooltipAnnotationReport(final StringBuilder tip,
+          SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
+          Map<String, float[][]> minmax)
+  {
+    int maxWidth = createSequenceAnnotationReport(tip, sequence,
+            showDbRefs, showNpFeats, minmax, true);
 
-    if (tableWrap && maxWidth > 60)
+    if (maxWidth > 60)
     {
-      tip.insert(0, "<table width=350 border=0><tr><td><i>");
-      tip.append("</i></td></tr></table>");
+      // ? not sure this serves any useful purpose
+      // tip.insert(0, "<table width=350 border=0><tr><td>");
+      // tip.append("</td></tr></table>");
     }
-
   }
 }
index 6b94559..af8a172 100755 (executable)
@@ -2181,6 +2181,19 @@ public class GAlignFrame extends JInternalFrame
         alignmentProperties();
       }
     });
+    JMenuItem selectHighlighted = new JMenuItem(
+            MessageManager.getString("action.select_highlighted_columns"));
+    selectHighlighted.setToolTipText(MessageManager
+            .getString("tooltip.select_highlighted_columns"));
+    al = new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        selectHighlightedColumns_actionPerformed(actionEvent);
+      }
+    };
+    selectHighlighted.addActionListener(al);
     JMenu tooltipSettingsMenu = new JMenu(
             MessageManager.getString("label.sequence_id_tooltip"));
     JMenu autoAnnMenu = new JMenu(
@@ -2382,12 +2395,20 @@ public class GAlignFrame extends JInternalFrame
     selectMenu.add(grpsFromSelection);
     selectMenu.add(deleteGroups);
     selectMenu.add(annotationColumn);
+    selectMenu.add(selectHighlighted);
     // TODO - determine if the listenToViewSelections button is needed : see bug
     // JAL-574
     // selectMenu.addSeparator();
     // selectMenu.add(listenToViewSelections);
   }
 
+  protected void selectHighlightedColumns_actionPerformed(
+          ActionEvent actionEvent)
+  {
+    // TODO Auto-generated method stub
+
+  }
+
   /**
    * Generate the reverse sequence (or reverse complement if the flag is true)
    * and add it to the alignment
index d7ae950..a0e530c 100644 (file)
@@ -28,7 +28,7 @@ import jalview.api.AlignViewportI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ResidueProperties;
 import jalview.util.Platform;
@@ -74,7 +74,7 @@ public class AnnotationRenderer
 
   private ColumnSelection columnSelection;
 
-  private ProfileI[] hconsensus;
+  private ProfilesI hconsensus;
 
   private Hashtable[] complementConsensus;
 
@@ -352,7 +352,7 @@ public class AnnotationRenderer
       {
         // TODO? group consensus for cDNA complement
         return AAFrequency.extractProfile(
-                aa.groupRef.consensusData[column],
+                aa.groupRef.consensusData.get(column),
                 aa.groupRef.getIgnoreGapsConsensus());
       }
       // TODO extend annotation row to enable dynamic and static profile data to
@@ -366,7 +366,8 @@ public class AnnotationRenderer
         }
         else
         {
-          return AAFrequency.extractProfile(hconsensus[column],
+          return AAFrequency.extractProfile(
+hconsensus.get(column),
                   av_ignoreGapsConsensus);
         }
       }
index b007365..9e0089f 100644 (file)
@@ -188,15 +188,20 @@ public class FeatureRenderer extends FeatureRendererModel
   }
 
   /**
-   * This is used by the Molecule Viewer and Overview to get the accurate colour
-   * of the rendered sequence
+   * This is used by Structure Viewers and the Overview Window to get the
+   * feature colour of the rendered sequence, returned as an RGB value
+   * 
+   * @param defaultColour
+   * @param seq
+   * @param column
+   * @return
    */
-  public synchronized int findFeatureColour(int initialCol,
+  public synchronized int findFeatureColour(int defaultColour,
           final SequenceI seq, int column)
   {
     if (!av.isShowSequenceFeatures())
     {
-      return initialCol;
+      return defaultColour;
     }
 
     SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
@@ -223,7 +228,7 @@ public class FeatureRenderer extends FeatureRendererModel
 
     if (lastSequenceFeatures == null || sfSize == 0)
     {
-      return initialCol;
+      return defaultColour;
     }
 
     if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column)))
@@ -244,7 +249,7 @@ public class FeatureRenderer extends FeatureRendererModel
 
     if (offscreenImage != null)
     {
-      offscreenImage.setRGB(0, 0, initialCol);
+      offscreenImage.setRGB(0, 0, defaultColour);
       drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0);
 
       return offscreenImage.getRGB(0, 0);
@@ -255,7 +260,7 @@ public class FeatureRenderer extends FeatureRendererModel
 
       if (currentColour == null)
       {
-        return initialCol;
+        return defaultColour;
       }
       else
       {
@@ -275,6 +280,19 @@ public class FeatureRenderer extends FeatureRendererModel
 
   int epos;
 
+  /**
+   * Draws the sequence on the graphics context, or just determines the colour
+   * that would be drawn (if flag offscreenrender is true).
+   * 
+   * @param g
+   * @param seq
+   * @param start
+   *          start column (or sequence position in offscreenrender mode)
+   * @param end
+   *          end column (not used in offscreenrender mode)
+   * @param y1
+   *          vertical offset at which to draw on the graphics
+   */
   public synchronized void drawSequence(Graphics g, final SequenceI seq,
           int start, int end, int y1)
   {
@@ -312,12 +330,10 @@ public class FeatureRenderer extends FeatureRendererModel
     }
 
     sfSize = lastSequenceFeatures.length;
-    String type;
     for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
     {
-      type = renderOrder[renderIndex];
-
-      if (type == null || !showFeatureOfType(type))
+      String type = renderOrder[renderIndex];
+      if (!showFeatureOfType(type))
       {
         continue;
       }
@@ -332,16 +348,16 @@ public class FeatureRenderer extends FeatureRendererModel
           continue;
         }
 
-        if (featureGroups != null
-                && sequenceFeature.featureGroup != null
-                && sequenceFeature.featureGroup.length() != 0
-                && featureGroups.containsKey(sequenceFeature.featureGroup)
-                && !featureGroups.get(sequenceFeature.featureGroup)
-                        .booleanValue())
+        if (featureGroupNotShown(sequenceFeature))
         {
           continue;
         }
 
+        /*
+         * check feature overlaps the visible part of the alignment, 
+         * unless doing offscreenRender (to the Overview window or a 
+         * structure viewer) which is not limited 
+         */
         if (!offscreenRender
                 && (sequenceFeature.getBegin() > epos || sequenceFeature
                         .getEnd() < spos))
@@ -349,35 +365,43 @@ public class FeatureRenderer extends FeatureRendererModel
           continue;
         }
 
+        Color featureColour = getColour(sequenceFeature);
+        boolean isContactFeature = sequenceFeature.isContactFeature();
+
         if (offscreenRender && offscreenImage == null)
         {
-          if (sequenceFeature.begin <= start
-                  && sequenceFeature.end >= start)
+          /*
+           * offscreen mode with no image (image is only needed if transparency 
+           * is applied to feature colours) - just check feature is rendered at 
+           * the requested position (start == sequence position in this mode)
+           */
+          boolean featureIsAtPosition = sequenceFeature.begin <= start
+                  && sequenceFeature.end >= start;
+          if (isContactFeature)
+          {
+            featureIsAtPosition = sequenceFeature.begin == start
+                    || sequenceFeature.end == start;
+          }
+          if (featureIsAtPosition)
           {
             // this is passed out to the overview and other sequence renderers
             // (e.g. molecule viewer) to get displayed colour for rendered
             // sequence
-            currentColour = new Integer(getColour(sequenceFeature).getRGB());
+            currentColour = new Integer(featureColour.getRGB());
             // used to be retreived from av.featuresDisplayed
             // currentColour = av.featuresDisplayed
             // .get(sequenceFeatures[sfindex].type);
 
           }
         }
-        else if (sequenceFeature.type.equals("disulfide bond"))
+        else if (isContactFeature)
         {
           renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
-                  seq.findIndex(sequenceFeature.begin) - 1,
-                  getColour(sequenceFeature)
-                  // new Color(((Integer) av.featuresDisplayed
-                  // .get(sequenceFeatures[sfindex].type)).intValue())
-                  , start, end, y1);
+                  seq.findIndex(sequenceFeature.begin) - 1, featureColour,
+                  start, end, y1);
           renderFeature(g, seq, seq.findIndex(sequenceFeature.end) - 1,
-                  seq.findIndex(sequenceFeature.end) - 1,
-                  getColour(sequenceFeature)
-                  // new Color(((Integer) av.featuresDisplayed
-                  // .get(sequenceFeatures[sfindex].type)).intValue())
-                  , start, end, y1);
+                  seq.findIndex(sequenceFeature.end) - 1, featureColour,
+                  start, end, y1);
 
         }
         else if (showFeature(sequenceFeature))
@@ -388,19 +412,17 @@ public class FeatureRenderer extends FeatureRendererModel
             renderScoreFeature(g, seq,
                     seq.findIndex(sequenceFeature.begin) - 1,
                     seq.findIndex(sequenceFeature.end) - 1,
-                    getColour(sequenceFeature), start, end, y1,
+                    featureColour, start, end, y1,
                     normaliseScore(sequenceFeature));
           }
           else
           {
             renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
                     seq.findIndex(sequenceFeature.end) - 1,
-                    getColour(sequenceFeature), start, end, y1);
+                    featureColour, start, end, y1);
           }
         }
-
       }
-
     }
 
     if (transparency != 1.0f && g != null)
@@ -412,6 +434,24 @@ public class FeatureRenderer extends FeatureRendererModel
   }
 
   /**
+   * Answers true if the feature belongs to a feature group which is not
+   * currently displayed, else false
+   * 
+   * @param sequenceFeature
+   * @return
+   */
+  protected boolean featureGroupNotShown(
+          final SequenceFeature sequenceFeature)
+  {
+    return featureGroups != null
+            && sequenceFeature.featureGroup != null
+            && sequenceFeature.featureGroup.length() != 0
+            && featureGroups.containsKey(sequenceFeature.featureGroup)
+            && !featureGroups.get(sequenceFeature.featureGroup)
+                    .booleanValue();
+  }
+
+  /**
    * Called when alignment in associated view has new/modified features to
    * discover and display.
    * 
index 37c31f9..c47f171 100755 (executable)
@@ -47,7 +47,7 @@ public class Blosum62ColourScheme extends ResidueColourScheme
       res -= ('a' - 'A');
     }
 
-    if (consensus == null || j >= consensus.length || consensus[j] == null
+    if (consensus == null || consensus.get(j) == null
             || (threshold != 0 && !aboveThreshold(res, j)))
     {
       return Color.white;
@@ -60,7 +60,7 @@ public class Blosum62ColourScheme extends ResidueColourScheme
       /*
        * test if this is the consensus (or joint consensus) residue
        */
-      String max = consensus[j].getModalResidue();
+      String max = consensus.get(j).getModalResidue();
 
       if (max.indexOf(res) > -1)
       {
index fb71686..da99a4a 100755 (executable)
@@ -21,7 +21,7 @@
 package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 
@@ -53,7 +53,7 @@ public interface ColourSchemeI
   /**
    * assign the given consensus profile for the colourscheme
    */
-  public void setConsensus(ProfileI[] hconsensus);
+  public void setConsensus(ProfilesI hconsensus);
 
   /**
    * assign the given conservation to the colourscheme
index 86fce4e..35be31b 100644 (file)
@@ -21,7 +21,7 @@
 package jalview.schemes;
 
 import jalview.analysis.Conservation;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
 
 /**
  * Colourscheme that takes its colours from some other colourscheme
@@ -40,7 +40,7 @@ public class FollowerColourScheme extends ResidueColourScheme
   }
 
   @Override
-  public void setConsensus(ProfileI[] consensus)
+  public void setConsensus(ProfilesI consensus)
   {
     if (colourScheme != null)
     {
index ccc69c2..0ad5b5c 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.schemes;
 
+import jalview.datamodel.ProfileI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.util.Comparison;
@@ -48,7 +49,7 @@ public class PIDColourScheme extends ResidueColourScheme
       c -= ('a' - 'A');
     }
 
-    if (consensus == null || j >= consensus.length || consensus[j] == null)
+    if (consensus == null || consensus.get(j) == null)
     {
       return Color.white;
     }
@@ -62,19 +63,16 @@ public class PIDColourScheme extends ResidueColourScheme
 
     double sc = 0;
 
-    if (consensus.length <= j)
-    {
-      return Color.white;
-    }
 
     /*
      * test whether this is the consensus (or joint consensus) residue
      */
-    boolean matchesConsensus = consensus[j].getModalResidue().contains(
+    ProfileI profile = consensus.get(j);
+    boolean matchesConsensus = profile.getModalResidue().contains(
             String.valueOf(c));
     if (matchesConsensus)
     {
-      sc = consensus[j].getPercentageIdentity(ignoreGaps);
+      sc = profile.getPercentageIdentity(ignoreGaps);
 
       if (!Comparison.isGap(c))
       {
index 31b8320..f6b7c5e 100755 (executable)
@@ -23,6 +23,7 @@ package jalview.schemes;
 import jalview.analysis.Conservation;
 import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 import jalview.util.ColorUtils;
@@ -54,7 +55,7 @@ public class ResidueColourScheme implements ColourSchemeI
   /*
    * Consensus data indexed by column
    */
-  ProfileI[] consensus;
+  ProfilesI consensus;
 
   /*
    * Conservation string as a char array 
@@ -182,19 +183,20 @@ public class ResidueColourScheme implements ColourSchemeI
       residue -= ('a' - 'A');
     }
 
-    if (consensus == null || consensus.length < column
-            || consensus[column] == null)
+    if (consensus == null)
     {
       return false;
     }
 
+    ProfileI profile = consensus.get(column);
+
     /*
      * test whether this is the consensus (or joint consensus) residue
      */
-    if (consensus[column].getModalResidue().contains(
-            String.valueOf(residue)))
+    if (profile != null
+            && profile.getModalResidue().contains(String.valueOf(residue)))
     {
-      if (consensus[column].getPercentageIdentity(ignoreGaps) >= threshold)
+      if (profile.getPercentageIdentity(ignoreGaps) >= threshold)
       {
         return true;
       }
@@ -234,7 +236,7 @@ public class ResidueColourScheme implements ColourSchemeI
    *          DOCUMENT ME!
    */
   @Override
-  public void setConsensus(ProfileI[] consensus)
+  public void setConsensus(ProfilesI consensus)
   {
     if (consensus == null)
     {
index 771b8a0..81ff739 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.structure;
 
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceI;
 
 public interface SequenceListener
@@ -27,7 +28,7 @@ public interface SequenceListener
   // TODO remove this? never called on SequenceListener type
   public void mouseOverSequence(SequenceI sequence, int index, int pos);
 
-  public void highlightSequence(jalview.datamodel.SearchResults results);
+  public void highlightSequence(SearchResultsI results);
 
   // TODO remove this? never called
   public void updateColours(SequenceI sequence, int index);
index cad2303..b3968a3 100644 (file)
@@ -31,6 +31,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JmolParser;
 import jalview.gui.IProgressIndicator;
@@ -805,7 +806,7 @@ public class StructureSelectionManager
       return;
     }
 
-    SearchResults results = new SearchResults();
+    SearchResultsI results = new SearchResults();
     for (AtomSpec atom : atoms)
     {
       SequenceI lastseq = null;
@@ -855,7 +856,7 @@ public class StructureSelectionManager
   {
     boolean hasSequenceListeners = handlingVamsasMo
             || !seqmappings.isEmpty();
-    SearchResults results = null;
+    SearchResultsI results = null;
     if (seqPos == -1)
     {
       seqPos = seq.findPosition(indexpos);
index b618bc0..2b3e23a 100644 (file)
@@ -136,19 +136,13 @@ public abstract class AAStructureBindingModel extends
    * @param protocol
    */
   public AAStructureBindingModel(StructureSelectionManager ssm,
-          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
-          String protocol)
+          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String protocol)
   {
     this.ssm = ssm;
     this.sequence = sequenceIs;
     this.nucleotide = Comparison.isNucleotide(sequenceIs);
-    this.chains = chains;
     this.pdbEntry = pdbentry;
     this.protocol = protocol;
-    if (chains == null)
-    {
-      this.chains = new String[pdbentry.length][];
-    }
   }
 
   public StructureSelectionManager getSsm()
@@ -677,6 +671,13 @@ public abstract class AAStructureBindingModel extends
   }
 
   /**
+   * Returns a list of chains mapped in this viewer.
+   * 
+   * @return
+   */
+  public abstract List<String> getChainNames();
+
+  /**
    * Returns the Jalview panel hosting the structure viewer (if any)
    * 
    * @return
index 1fe452d..f35339c 100644 (file)
@@ -31,8 +31,9 @@ import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
-import jalview.datamodel.SearchResults.Match;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -194,7 +195,7 @@ public final class MappingUtils
       /*
        * Determine all mappings from this position to mapped sequences.
        */
-      SearchResults sr = buildSearchResults(seq, seqpos, mappings);
+      SearchResultsI sr = buildSearchResults(seq, seqpos, mappings);
 
       if (!sr.isEmpty())
       {
@@ -266,10 +267,10 @@ public final class MappingUtils
    * @param seqmappings
    * @return
    */
-  public static SearchResults buildSearchResults(SequenceI seq, int index,
+  public static SearchResultsI buildSearchResults(SequenceI seq, int index,
           List<AlignedCodonFrame> seqmappings)
   {
-    SearchResults results = new SearchResults();
+    SearchResultsI results = new SearchResults();
     addSearchResults(results, seq, index, seqmappings);
     return results;
   }
@@ -283,7 +284,7 @@ public final class MappingUtils
    * @param index
    * @param seqmappings
    */
-  public static void addSearchResults(SearchResults results, SequenceI seq,
+  public static void addSearchResults(SearchResultsI results, SequenceI seq,
           int index, List<AlignedCodonFrame> seqmappings)
   {
     if (index >= seq.getStart() && index <= seq.getEnd())
@@ -376,15 +377,15 @@ public final class MappingUtils
                */
               List<AlignedCodonFrame> mapping = Arrays
                       .asList(new AlignedCodonFrame[] { acf });
-              SearchResults sr = buildSearchResults(selected,
+              SearchResultsI sr = buildSearchResults(selected,
                       startResiduePos, mapping);
-              for (Match m : sr.getResults())
+              for (SearchResultMatchI m : sr.getResults())
               {
                 mappedStartResidue = m.getStart();
                 mappedEndResidue = m.getEnd();
               }
               sr = buildSearchResults(selected, endResiduePos, mapping);
-              for (Match m : sr.getResults())
+              for (SearchResultMatchI m : sr.getResults())
               {
                 mappedStartResidue = Math.min(mappedStartResidue,
                         m.getStart());
@@ -647,8 +648,8 @@ public final class MappingUtils
        * Get the residue position and find the mapped position.
        */
       int residuePos = fromSeq.findPosition(col);
-      SearchResults sr = buildSearchResults(fromSeq, residuePos, mappings);
-      for (Match m : sr.getResults())
+      SearchResultsI sr = buildSearchResults(fromSeq, residuePos, mappings);
+      for (SearchResultMatchI m : sr.getResults())
       {
         int mappedStartResidue = m.getStart();
         int mappedEndResidue = m.getEnd();
index e6b45f2..7fd9792 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import jalview.ext.android.SparseIntArray;
index 57258ef..fecccb0 100644 (file)
@@ -36,8 +36,8 @@ import jalview.datamodel.Annotation;
 import jalview.datamodel.CigarArray;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenSequences;
-import jalview.datamodel.ProfileI;
-import jalview.datamodel.SearchResults;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
@@ -701,7 +701,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   /**
    * results of alignment consensus analysis for visible portion of view
    */
-  protected ProfileI[] hconsensus = null;
+  protected ProfilesI hconsensus = null;
 
   /**
    * results of cDNA complement consensus visible portion of view
@@ -735,7 +735,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
-  public void setSequenceConsensusHash(ProfileI[] hconsensus)
+  public void setSequenceConsensusHash(ProfilesI hconsensus)
   {
     this.hconsensus = hconsensus;
   }
@@ -747,7 +747,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
-  public ProfileI[] getSequenceConsensusHash()
+  public ProfilesI getSequenceConsensusHash()
   {
     return hconsensus;
   }
@@ -2718,7 +2718,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    *          the SearchResults to add to
    * @return the offset (below top of visible region) of the matched sequence
    */
-  protected int findComplementScrollTarget(SearchResults sr)
+  protected int findComplementScrollTarget(SearchResultsI sr)
   {
     final AlignViewportI complement = getCodingComplement();
     if (complement == null || !complement.isFollowHighlight())
@@ -2825,6 +2825,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    */
   private boolean selectionIsDefinedGroup = false;
 
+
   @Override
   public boolean isSelectionDefinedGroup()
   {
@@ -2848,4 +2849,27 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return selectionGroup.getContext() == alignment
             || selectionIsDefinedGroup;
   }
+
+  /**
+   * null, or currently highlighted results on this view
+   */
+  private SearchResultsI searchResults = null;
+
+  @Override
+  public boolean hasSearchResults()
+  {
+    return searchResults != null;
+  }
+
+  @Override
+  public void setSearchResults(SearchResultsI results)
+  {
+    searchResults = results;
+  }
+
+  @Override
+  public SearchResultsI getSearchResults()
+  {
+    return searchResults;
+  }
 }
index 4ac4804..c1ad465 100644 (file)
@@ -288,8 +288,12 @@ public abstract class FeatureRendererModel implements
           continue;
         }
 
-        if ((features[i].getBegin() <= res)
-                && (features[i].getEnd() >= res))
+        // check if start/end are at res, and if not a contact feature, that res
+        // lies between start and end
+        if ((features[i].getBegin() == res || features[i].getEnd() == res)
+                || (!features[i].isContactFeature()
+                        && (features[i].getBegin() < res) && (features[i]
+                        .getEnd() >= res)))
         {
           tmp.add(features[i]);
         }
@@ -564,9 +568,16 @@ public abstract class FeatureRendererModel implements
     return fc.isColored(sequenceFeature);
   }
 
+  /**
+   * Answers true if the feature type is currently selected to be displayed,
+   * else false
+   * 
+   * @param type
+   * @return
+   */
   protected boolean showFeatureOfType(String type)
   {
-    return av.getFeaturesDisplayed().isVisible(type);
+    return type == null ? false : av.getFeaturesDisplayed().isVisible(type);
   }
 
   @Override
index 2b11477..debe45d 100644 (file)
@@ -26,7 +26,7 @@ import jalview.api.AlignmentViewPanel;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SequenceI;
 import jalview.schemes.ColourSchemeI;
 
@@ -124,10 +124,11 @@ public class ConsensusThread extends AlignCalcWorker
    */
   protected void computeConsensus(AlignmentI alignment)
   {
-    ProfileI[] hconsensus = new ProfileI[alignment.getWidth()];
 
     SequenceI[] aseqs = getSequences();
-    AAFrequency.calculate(aseqs, 0, alignment.getWidth(), hconsensus, true);
+    int width = alignment.getWidth();
+    ProfilesI hconsensus = AAFrequency.calculate(aseqs, width, 0,
+            width, true);
 
     alignViewport.setSequenceConsensusHash(hconsensus);
     setColourSchemeConsensus(hconsensus);
@@ -144,7 +145,7 @@ public class ConsensusThread extends AlignCalcWorker
   /**
    * @param hconsensus
    */
-  protected void setColourSchemeConsensus(ProfileI[] hconsensus)
+  protected void setColourSchemeConsensus(ProfilesI hconsensus)
   {
     ColourSchemeI globalColourScheme = alignViewport
             .getGlobalColourScheme();
@@ -177,7 +178,7 @@ public class ConsensusThread extends AlignCalcWorker
   public void updateResultAnnotation(boolean immediate)
   {
     AlignmentAnnotation consensus = getConsensusAnnotation();
-    ProfileI[] hconsensus = (ProfileI[]) getViewportConsensus();
+    ProfilesI hconsensus = (ProfilesI) getViewportConsensus();
     if (immediate || !calcMan.isWorking(this) && consensus != null
             && hconsensus != null)
     {
@@ -195,11 +196,14 @@ public class ConsensusThread extends AlignCalcWorker
    *          the computed consensus data
    */
   protected void deriveConsensus(AlignmentAnnotation consensusAnnotation,
-          ProfileI[] hconsensus)
+          ProfilesI hconsensus)
   {
+
     long nseq = getSequences().length;
-    AAFrequency.completeConsensus(consensusAnnotation, hconsensus, 0,
-            hconsensus.length, alignViewport.isIgnoreGapsConsensus(),
+    AAFrequency.completeConsensus(consensusAnnotation, hconsensus,
+            hconsensus.getStartColumn(),
+            hconsensus.getEndColumn() + 1,
+            alignViewport.isIgnoreGapsConsensus(),
             alignViewport.isShowSequenceLogo(), nseq);
   }
 
@@ -208,7 +212,7 @@ public class ConsensusThread extends AlignCalcWorker
    * 
    * @return
    */
-  protected Object[] getViewportConsensus()
+  protected Object getViewportConsensus()
   {
     // TODO convert ComplementConsensusThread to use Profile
     return alignViewport.getSequenceConsensusHash();
index eb094da..27db604 100644 (file)
@@ -511,13 +511,13 @@ public class SiftsClient implements SiftsClientI
     if (os != null)
     {
       MappingOutputPojo mop = new MappingOutputPojo();
-      mop.setSeqStart(pdbStart);
-      mop.setSeqEnd(pdbEnd);
+      mop.setSeqStart(seqStart);
+      mop.setSeqEnd(seqEnd);
       mop.setSeqName(seq.getName());
       mop.setSeqResidue(matchedSeq);
 
-      mop.setStrStart(seqStart);
-      mop.setStrEnd(seqEnd);
+      mop.setStrStart(pdbStart);
+      mop.setStrEnd(pdbEnd);
       mop.setStrName(structId);
       mop.setStrResidue(targetStrucSeqs.toString());
 
index 1c04b8e..58601a9 100644 (file)
@@ -26,6 +26,7 @@ import static org.testng.AssertJUnit.assertNull;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 
@@ -41,12 +42,12 @@ public class AAFrequencyTest
     SequenceI seq3 = new Sequence("Seq3", "C---G");
     SequenceI seq4 = new Sequence("Seq4", "CA--t");
     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
-    ProfileI[] result = new ProfileI[seq1.getLength()];
-
-    AAFrequency.calculate(seqs, 0, seq1.getLength(), result, false);
+    int width = seq1.getLength();
+    ProfilesI result = AAFrequency.calculate(seqs, width, 0, width,
+            false);
 
     // col 0 is 100% C
-    ProfileI col = result[0];
+    ProfileI col = result.get(0);
     assertEquals(100f, col.getPercentageIdentity(false));
     assertEquals(100f, col.getPercentageIdentity(true));
     assertEquals(4, col.getMaxCount());
@@ -54,28 +55,28 @@ public class AAFrequencyTest
     assertNull(col.getCounts());
 
     // col 1 is 75% A
-    col = result[1];
+    col = result.get(1);
     assertEquals(75f, col.getPercentageIdentity(false));
     assertEquals(100f, col.getPercentageIdentity(true));
     assertEquals(3, col.getMaxCount());
     assertEquals("A", col.getModalResidue());
 
     // col 2 is 50% G 50% C or 25/25 counting gaps
-    col = result[2];
+    col = result.get(2);
     assertEquals(25f, col.getPercentageIdentity(false));
     assertEquals(50f, col.getPercentageIdentity(true));
     assertEquals(1, col.getMaxCount());
     assertEquals("CG", col.getModalResidue());
 
     // col 3 is all gaps
-    col = result[3];
+    col = result.get(3);
     assertEquals(0f, col.getPercentageIdentity(false));
     assertEquals(0f, col.getPercentageIdentity(true));
     assertEquals(0, col.getMaxCount());
     assertEquals("", col.getModalResidue());
 
     // col 4 is 75% T 25% G
-    col = result[4];
+    col = result.get(4);
     assertEquals(75f, col.getPercentageIdentity(false));
     assertEquals(75f, col.getPercentageIdentity(true));
     assertEquals(3, col.getMaxCount());
@@ -90,26 +91,27 @@ public class AAFrequencyTest
     SequenceI seq3 = new Sequence("Seq3", "C--G");
     SequenceI seq4 = new Sequence("Seq4", "CA-t");
     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
-    ProfileI[] result = new ProfileI[seq1.getLength()];
+    int width = seq1.getLength();
+    ProfilesI result = AAFrequency.calculate(seqs, width, 0, width,
+            true);
 
-    AAFrequency.calculate(seqs, 0, seq1.getLength(), result, true);
-    ProfileI profile = result[0];
+    ProfileI profile = result.get(0);
     assertEquals(4, profile.getCounts().getCount('C'));
     assertEquals(4, profile.getHeight());
     assertEquals(4, profile.getNonGapped());
 
-    profile = result[1];
+    profile = result.get(1);
     assertEquals(3, profile.getCounts().getCount('A'));
     assertEquals(4, profile.getHeight());
     assertEquals(3, profile.getNonGapped());
 
-    profile = result[2];
+    profile = result.get(2);
     assertEquals(1, profile.getCounts().getCount('C'));
     assertEquals(1, profile.getCounts().getCount('G'));
     assertEquals(4, profile.getHeight());
     assertEquals(2, profile.getNonGapped());
 
-    profile = result[3];
+    profile = result.get(3);
     assertEquals(3, profile.getCounts().getCount('T'));
     assertEquals(1, profile.getCounts().getCount('G'));
     assertEquals(4, profile.getHeight());
@@ -124,15 +126,16 @@ public class AAFrequencyTest
     SequenceI seq3 = new Sequence("Seq3", "C--G");
     SequenceI seq4 = new Sequence("Seq4", "CA-t");
     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
-    ProfileI[] result = new ProfileI[seq1.getLength()];
 
-    // ensure class loaded and initialized
-    AAFrequency.calculate(seqs, 0, seq1.getLength(), result, true);
+    // ensure class loaded and initialised
+    int width = seq1.getLength();
+    AAFrequency.calculate(seqs, width, 0, width, true);
+
     int reps = 100000;
     long start = System.currentTimeMillis();
     for (int i = 0; i < reps; i++)
     {
-      AAFrequency.calculate(seqs, 0, seq1.getLength(), result, true);
+      AAFrequency.calculate(seqs, width, 0, width, true);
     }
     System.out.println(System.currentTimeMillis() - start);
   }
@@ -154,11 +157,11 @@ public class AAFrequencyTest
     SequenceI seq3 = new Sequence("Seq3", "C---G");
     SequenceI seq4 = new Sequence("Seq4", "CA--t");
     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
-    ProfileI[] profiles = new ProfileI[seq1.getLength()];
-    AAFrequency.calculate(seqs, 0, seq1.getLength(), profiles, true);
+    int width = seq1.getLength();
+    ProfilesI profiles = AAFrequency.calculate(seqs, width, 0, width, true);
 
     AlignmentAnnotation consensus = new AlignmentAnnotation("Consensus",
-            "PID", new Annotation[seq1.getLength()]);
+            "PID", new Annotation[width]);
     AAFrequency
             .completeConsensus(consensus, profiles, 0, 5, false, true, 4);
 
@@ -195,11 +198,11 @@ public class AAFrequencyTest
     SequenceI seq3 = new Sequence("Seq3", "C---G");
     SequenceI seq4 = new Sequence("Seq4", "CA--t");
     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
-    ProfileI[] profiles = new ProfileI[seq1.getLength()];
-    AAFrequency.calculate(seqs, 0, seq1.getLength(), profiles, true);
+    int width = seq1.getLength();
+    ProfilesI profiles = AAFrequency.calculate(seqs, width, 0, width, true);
   
     AlignmentAnnotation consensus = new AlignmentAnnotation("Consensus",
-            "PID", new Annotation[seq1.getLength()]);
+            "PID", new Annotation[width]);
     AAFrequency
             .completeConsensus(consensus, profiles, 0, 5, true, false, 4);
   
index 4aed7e7..449514a 100644 (file)
@@ -35,8 +35,8 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.Mapping;
-import jalview.datamodel.SearchResults;
-import jalview.datamodel.SearchResults.Match;
+import jalview.datamodel.SearchResultMatchI;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
@@ -1119,9 +1119,9 @@ public class AlignmentUtilsTests
     assertEquals(1, mappings.size());
 
     // map G to GGG
-    SearchResults sr = MappingUtils.buildSearchResults(pep1, 1, mappings);
+    SearchResultsI sr = MappingUtils.buildSearchResults(pep1, 1, mappings);
     assertEquals(1, sr.getResults().size());
-    Match m = sr.getResults().get(0);
+    SearchResultMatchI m = sr.getResults().get(0);
     assertSame(cds1Dss, m.getSequence());
     assertEquals(1, m.getStart());
     assertEquals(3, m.getEnd());
@@ -1650,10 +1650,10 @@ public class AlignmentUtilsTests
     List<AlignedCodonFrame> pep1CdsMappings = MappingUtils
             .findMappingsForSequence(cds.getSequenceAt(0), pep1Mappings);
     assertEquals(1, pep1CdsMappings.size());
-    SearchResults sr = MappingUtils.buildSearchResults(pep1, 1,
+    SearchResultsI sr = MappingUtils.buildSearchResults(pep1, 1,
             pep1CdsMappings);
     assertEquals(1, sr.getResults().size());
-    Match m = sr.getResults().get(0);
+    SearchResultMatchI m = sr.getResults().get(0);
     assertEquals(cds.getSequenceAt(0).getDatasetSequence(), m.getSequence());
     assertEquals(1, m.getStart());
     assertEquals(3, m.getEnd());
@@ -2388,9 +2388,9 @@ public class AlignmentUtilsTests
     assertEquals(1, mappings.size());
 
     // map G to GGG
-    SearchResults sr = MappingUtils.buildSearchResults(pep3, 1, mappings);
+    SearchResultsI sr = MappingUtils.buildSearchResults(pep3, 1, mappings);
     assertEquals(1, sr.getResults().size());
-    Match m = sr.getResults().get(0);
+    SearchResultMatchI m = sr.getResults().get(0);
     assertSame(cds.getSequenceAt(0).getDatasetSequence(), m.getSequence());
     assertEquals(1, m.getStart());
     assertEquals(3, m.getEnd());
index 123fcd6..39eb309 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis;
 
 import static org.testng.Assert.assertEquals;
diff --git a/test/jalview/analysis/FinderTest.java b/test/jalview/analysis/FinderTest.java
new file mode 100644 (file)
index 0000000..91ceb82
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.analysis;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SearchResultMatchI;
+import jalview.datamodel.SearchResultsI;
+import jalview.datamodel.Sequence;
+import jalview.gui.AlignFrame;
+import jalview.io.FileLoader;
+import jalview.io.FormatAdapter;
+
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class FinderTest
+{
+  private AlignFrame af;
+
+  private AlignmentI al;
+
+  @BeforeClass(groups = "Functional")
+  public void setUp()
+  {
+    String seqData = "seq1 ABCD--EF-GHI\n" + "seq2 A--BCDefHI\n"
+            + "seq3 --bcdEFH\n" + "seq4 aa---aMMMMMaaa\n";
+    af = new FileLoader().LoadFileWaitTillLoaded(seqData,
+            FormatAdapter.PASTE);
+    al = af.getViewport().getAlignment();
+  }
+
+  /**
+   * Test for find all matches of a regular expression
+   */
+  @Test(groups = "Functional")
+  public void testFindAll_regex()
+  {
+    Finder f = new Finder(al, null);
+    f.setFindAll(true);
+    f.find("E.H"); // 'E, any character, H'
+
+    // should match seq2 efH and seq3 EFH
+    SearchResultsI sr = f.getSearchResults();
+    assertEquals(sr.getSize(), 2);
+    List<SearchResultMatchI> matches = sr.getResults();
+    assertSame(al.getSequenceAt(1), matches.get(0).getSequence());
+    assertSame(al.getSequenceAt(2), matches.get(1).getSequence());
+    assertEquals(matches.get(0).getStart(), 5);
+    assertEquals(matches.get(0).getEnd(), 7);
+    assertEquals(matches.get(1).getStart(), 4);
+    assertEquals(matches.get(1).getEnd(), 6);
+  }
+
+  /**
+   * Test for (undocumented) find residue by position
+   */
+  @Test(groups = "Functional")
+  public void testFind_residueNumber()
+  {
+    Finder f = new Finder(al, null);
+    f.setFindAll(true);
+    f.find("9");
+
+    // seq1 and seq4 have 9 residues; no match in other sequences
+    SearchResultsI sr = f.getSearchResults();
+    assertEquals(sr.getSize(), 2);
+    List<SearchResultMatchI> matches = sr.getResults();
+    assertSame(al.getSequenceAt(0), matches.get(0).getSequence());
+    assertSame(al.getSequenceAt(3), matches.get(1).getSequence());
+    assertEquals(matches.get(0).getStart(), 9);
+    assertEquals(matches.get(0).getEnd(), 9);
+    assertEquals(matches.get(1).getStart(), 9);
+    assertEquals(matches.get(1).getEnd(), 9);
+  }
+
+  /**
+   * Test for find next action
+   */
+  @Test(groups = "Functional")
+  public void testFindNext()
+  {
+    /*
+     * start at second sequence; resIndex of -1
+     * means sequence id / description is searched
+     */
+    Finder f = new Finder(al, null, 1, -1);
+    f.find("e"); // matches id
+
+    assertTrue(f.getSearchResults().isEmpty());
+    assertEquals(f.getIdMatch().size(), 1);
+    assertSame(f.getIdMatch().get(0), al.getSequenceAt(1));
+
+    // resIndex is now 0 - for use in next find next
+    assertEquals(f.getResIndex(), 0);
+    f = new Finder(al, null, 1, 0);
+    f.find("e"); // matches in sequence
+    assertTrue(f.getIdMatch().isEmpty());
+    assertEquals(f.getSearchResults().getSize(), 1);
+    List<SearchResultMatchI> matches = f.getSearchResults().getResults();
+    assertEquals(matches.get(0).getStart(), 5);
+    assertEquals(matches.get(0).getEnd(), 5);
+    assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
+    // still in the second sequence
+    assertEquals(f.getSeqIndex(), 1);
+    // next residue position to search from is 5
+    // (used as base 0 by RegEx so the same as 6 if base 1)
+    assertEquals(f.getResIndex(), 5);
+
+    // find next from end of sequence - finds next sequence id
+    f = new Finder(al, null, 1, 5);
+    f.find("e");
+    assertEquals(f.getIdMatch().size(), 1);
+    assertSame(f.getIdMatch().get(0), al.getSequenceAt(2));
+  }
+
+  /**
+   * Test for matching within sequence descriptions
+   */
+  @Test(groups = "Functional")
+  public void testFindAll_inDescription()
+  {
+    AlignmentI al2 = new Alignment(al);
+    al2.getSequenceAt(0).setDescription("BRAF");
+    al2.getSequenceAt(1).setDescription("braf");
+    Finder f = new Finder(al2, null);
+    f.setFindAll(true);
+    f.setIncludeDescription(true);
+
+    f.find("rAF");
+    assertEquals(f.getIdMatch().size(), 2);
+    assertSame(f.getIdMatch().get(0), al2.getSequenceAt(0));
+    assertSame(f.getIdMatch().get(1), al2.getSequenceAt(1));
+    assertTrue(f.getSearchResults().isEmpty());
+
+    /*
+     * case sensitive
+     */
+    f = new Finder(al2, null);
+    f.setFindAll(true);
+    f.setCaseSensitive(true);
+    f.setIncludeDescription(true);
+
+    f.find("RAF");
+    assertEquals(f.getIdMatch().size(), 1);
+    assertSame(f.getIdMatch().get(0), al2.getSequenceAt(0));
+    assertTrue(f.getSearchResults().isEmpty());
+
+    /*
+     * match sequence id, description and sequence!
+     */
+    al2.getSequenceAt(0).setDescription("the efh sequence");
+    al2.getSequenceAt(0).setName("mouseEFHkinase");
+    al2.getSequenceAt(1).setName("humanEFHkinase");
+    f = new Finder(al2, null);
+    f.setFindAll(true);
+    f.setIncludeDescription(true);
+
+    /*
+     * sequence matches should have no duplicates
+     */
+    f.find("EFH");
+    assertEquals(f.getIdMatch().size(), 2);
+    assertSame(f.getIdMatch().get(0), al2.getSequenceAt(0));
+    assertSame(f.getIdMatch().get(1), al2.getSequenceAt(1));
+
+    assertEquals(f.getSearchResults().getSize(), 2);
+    SearchResultMatchI match = f.getSearchResults().getResults().get(0);
+    assertSame(al2.getSequenceAt(1), match.getSequence());
+    assertEquals(5, match.getStart());
+    assertEquals(7, match.getEnd());
+    match = f.getSearchResults().getResults().get(1);
+    assertSame(al2.getSequenceAt(2), match.getSequence());
+    assertEquals(4, match.getStart());
+    assertEquals(6, match.getEnd());
+  }
+
+  /**
+   * Test for matching within sequence ids
+   */
+  @Test(groups = "Functional")
+  public void testFindAll_sequenceIds()
+  {
+    Finder f = new Finder(al, null);
+    f.setFindAll(true);
+
+    /*
+     * case insensitive
+     */
+    f.find("SEQ1");
+    assertEquals(f.getIdMatch().size(), 1);
+    assertSame(f.getIdMatch().get(0), al.getSequenceAt(0));
+    assertTrue(f.getSearchResults().isEmpty());
+
+    /*
+     * case sensitive
+     */
+    f = new Finder(al, null);
+    f.setFindAll(true);
+    f.setCaseSensitive(true);
+    f.find("SEQ1");
+    assertTrue(f.getSearchResults().isEmpty());
+
+    /*
+     * match both sequence id and sequence
+     */
+    AlignmentI al2 = new Alignment(al);
+    al2.addSequence(new Sequence("aBz", "xyzabZpqrAbZ"));
+    f = new Finder(al2, null);
+    f.setFindAll(true);
+    f.find("ABZ");
+    assertEquals(f.getIdMatch().size(), 1);
+    assertSame(f.getIdMatch().get(0), al2.getSequenceAt(4));
+    assertEquals(f.getSearchResults().getSize(), 2);
+    SearchResultMatchI match = f.getSearchResults().getResults().get(0);
+    assertSame(al2.getSequenceAt(4), match.getSequence());
+    assertEquals(4, match.getStart());
+    assertEquals(6, match.getEnd());
+    match = f.getSearchResults().getResults().get(1);
+    assertSame(al2.getSequenceAt(4), match.getSequence());
+    assertEquals(10, match.getStart());
+    assertEquals(12, match.getEnd());
+  }
+
+  /**
+   * Test finding all matches of a sequence pattern in an alignment
+   */
+  @Test(groups = "Functional")
+  public void testFindAll_simpleMatch()
+  {
+    Finder f = new Finder(al, null);
+    f.setFindAll(true);
+
+    /*
+     * case insensitive first
+     */
+    f.find("EfH");
+    SearchResultsI searchResults = f.getSearchResults();
+    assertEquals(searchResults.getSize(), 2);
+    SearchResultMatchI match = searchResults.getResults().get(0);
+    assertSame(al.getSequenceAt(1), match.getSequence());
+    assertEquals(5, match.getStart());
+    assertEquals(7, match.getEnd());
+    match = searchResults.getResults().get(1);
+    assertSame(al.getSequenceAt(2), match.getSequence());
+    assertEquals(4, match.getStart());
+    assertEquals(6, match.getEnd());
+
+    /*
+     * case sensitive
+     */
+    f = new Finder(al, null);
+    f.setFindAll(true);
+    f.setCaseSensitive(true);
+    f.find("BC");
+    searchResults = f.getSearchResults();
+    assertEquals(searchResults.getSize(), 2);
+    match = searchResults.getResults().get(0);
+    assertSame(al.getSequenceAt(0), match.getSequence());
+    assertEquals(2, match.getStart());
+    assertEquals(3, match.getEnd());
+    match = searchResults.getResults().get(1);
+    assertSame(al.getSequenceAt(1), match.getSequence());
+    assertEquals(2, match.getStart());
+    assertEquals(3, match.getEnd());
+  }
+
+  /**
+   * Test for JAL-2302 to verify that sub-matches are not included in a find all
+   * result
+   */
+  @Test(groups = "Functional")
+  public void testFind_maximalResultOnly()
+  {
+    Finder f = new Finder(al, null);
+    f.setFindAll(true);
+    f.find("M+");
+    SearchResultsI searchResults = f.getSearchResults();
+    assertEquals(searchResults.getSize(), 1);
+    SearchResultMatchI match = searchResults.getResults().get(0);
+    assertSame(al.getSequenceAt(3), match.getSequence());
+    assertEquals(4, match.getStart()); // dataset sequence positions
+    assertEquals(8, match.getEnd()); // base 1
+  }
+}
index 309790f..292b576 100644 (file)
@@ -27,6 +27,8 @@ import jalview.gui.AlignFrame;
 import jalview.io.FileLoader;
 import jalview.io.FormatAdapter;
 
+import java.util.Arrays;
+
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -137,4 +139,45 @@ public class FeatureScoreModelTest
               + "(" + s + ") should still be distinct from FER1_MAIZE (3)");
     }
   }
+
+  /**
+   * Check findFeatureAt doesn't return contact features except at contact
+   * points TODO:move to under the FeatureRendererModel test suite
+   */
+  @Test(groups = { "Functional" })
+  public void testFindFeatureAt_PointFeature() throws Exception
+  {
+    String alignment = "a CCCCCCGGGGGGCCCCCC\n" + "b CCCCCCGGGGGGCCCCCC\n"
+            + "c CCCCCCGGGGGGCCCCCC\n";
+    AlignFrame af = new jalview.io.FileLoader(false)
+            .LoadFileWaitTillLoaded(alignment, FormatAdapter.PASTE);
+    SequenceI aseq = af.getViewport().getAlignment().getSequenceAt(0);
+    SequenceFeature sf = null;
+    sf = new SequenceFeature("disulphide bond", "", 2, 5, Float.NaN, "");
+    aseq.addSequenceFeature(sf);
+    Assert.assertTrue(sf.isContactFeature());
+    af.refreshFeatureUI(true);
+    af.getFeatureRenderer().setAllVisible(Arrays.asList("disulphide bond"));
+    Assert.assertEquals(af.getFeatureRenderer().getDisplayedFeatureTypes()
+            .size(), 1, "Should be just one feature type displayed");
+    // step through and check for pointwise feature presence/absence
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 1)
+            .size(), 0);
+    // step through and check for pointwise feature presence/absence
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 2)
+            .size(), 1);
+    // step through and check for pointwise feature presence/absence
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 3)
+            .size(), 0);
+    // step through and check for pointwise feature presence/absence
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 4)
+            .size(), 0);
+    // step through and check for pointwise feature presence/absence
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 5)
+            .size(), 1);
+    // step through and check for pointwise feature presence/absence
+    Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 6)
+            .size(), 0);
+  }
+
 }
index 7fd8965..e2c2130 100644 (file)
@@ -23,11 +23,19 @@ package jalview.controller;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.analysis.Finder;
+import jalview.api.AlignViewControllerI;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.io.FileLoader;
+import jalview.io.FormatAdapter;
 
+import java.util.Arrays;
 import java.util.BitSet;
 
 import org.testng.annotations.Test;
@@ -37,10 +45,10 @@ public class AlignViewControllerTest
   @Test(groups = "Functional")
   public void testFindColumnsWithFeature()
   {
-    SequenceI seq1 = new Sequence("seq1", "aMMMaaaaaaaaaaaaaaaa");
-    SequenceI seq2 = new Sequence("seq2", "aaaMMMMMMMaaaaaaaaaa");
-    SequenceI seq3 = new Sequence("seq3", "aaaaaaaaaaMMMMMaaaaa");
-    SequenceI seq4 = new Sequence("seq3", "aaaaaaaaaaaaaaaaaaaa");
+    SequenceI seq1 = new Sequence("seq1", "-a-MMMaaaaaaaaaaaaaaaa");
+    SequenceI seq2 = new Sequence("seq2", "aa--aMM-MMMMMaaaaaaaaaa");
+    SequenceI seq3 = new Sequence("seq3", "abcab-caD-aaMMMMMaaaaa");
+    SequenceI seq4 = new Sequence("seq4", "abc--abcaaaaaaaaaaaaaa");
 
     /*
      * features start/end are base 1
@@ -53,13 +61,16 @@ public class AlignViewControllerTest
             null));
     seq3.addSequenceFeature(new SequenceFeature("Metal", "desc", 11, 15,
             0f, null));
+    // disulfide bond is a 'contact feature' - only select its 'start' and 'end'
+    seq3.addSequenceFeature(new SequenceFeature("disulfide bond", "desc", 8, 12,
+            0f, null));
 
     /*
-     * select the first three columns --> Metal in seq1 2-3
+     * select the first five columns --> Metal in seq1 cols 4-5
      */
     SequenceGroup sg = new SequenceGroup();
     sg.setStartRes(0); // base 0
-    sg.setEndRes(2);
+    sg.setEndRes(4);
     sg.addSequence(seq1, false);
     sg.addSequence(seq2, false);
     sg.addSequence(seq3, false);
@@ -70,36 +81,37 @@ public class AlignViewControllerTest
             bs);
     assertEquals(1, seqCount);
     assertEquals(2, bs.cardinality());
-    assertTrue(bs.get(1));
-    assertTrue(bs.get(2));
+    assertTrue(bs.get(3)); // base 0
+    assertTrue(bs.get(4));
 
     /*
-     * select the first four columns: Metal in seq1 2:4, seq2 4:4
+     * select the first seven columns: Metal in seq1 cols 4-6, seq2 cols 6-7 
      */
-    sg.setEndRes(3);
+    sg.setEndRes(6);
     bs.clear();
     seqCount = AlignViewController.findColumnsWithFeature("Metal", sg, bs);
     assertEquals(2, seqCount);
-    assertEquals(3, bs.cardinality());
-    assertTrue(bs.get(1));
-    assertTrue(bs.get(2));
+    assertEquals(4, bs.cardinality());
     assertTrue(bs.get(3));
+    assertTrue(bs.get(4));
+    assertTrue(bs.get(5));
+    assertTrue(bs.get(6));
 
     /*
-     * select column 11: Metal in seq3 only
+     * select column 14: Metal in seq3 only
      */
-    sg.setStartRes(10);
-    sg.setEndRes(10);
+    sg.setStartRes(13);
+    sg.setEndRes(13);
     bs.clear();
     seqCount = AlignViewController.findColumnsWithFeature("Metal", sg, bs);
     assertEquals(1, seqCount);
     assertEquals(1, bs.cardinality());
-    assertTrue(bs.get(10));
+    assertTrue(bs.get(13));
 
     /*
-     * select columns 16-20: no Metal feature
+     * select columns 18-20: no Metal feature
      */
-    sg.setStartRes(15);
+    sg.setStartRes(17);
     sg.setEndRes(19);
     bs.clear();
     seqCount = AlignViewController.findColumnsWithFeature("Metal", sg, bs);
@@ -107,6 +119,30 @@ public class AlignViewControllerTest
     assertEquals(0, bs.cardinality());
 
     /*
+     * columns 11-13 should not match disulfide bond at 8/12
+     */
+    sg.setStartRes(10);
+    sg.setEndRes(12);
+    bs.clear();
+    seqCount = AlignViewController.findColumnsWithFeature("disulfide bond",
+            sg, bs);
+    assertEquals(0, seqCount);
+    assertEquals(0, bs.cardinality());
+
+    /*
+     * columns 6-18 should match disulfide bond at columns 9, 14
+     */
+    sg.setStartRes(5);
+    sg.setEndRes(17);
+    bs.clear();
+    seqCount = AlignViewController.findColumnsWithFeature("disulfide bond",
+            sg, bs);
+    assertEquals(1, seqCount);
+    assertEquals(2, bs.cardinality());
+    assertTrue(bs.get(8));
+    assertTrue(bs.get(13));
+
+    /*
      * look for a feature that isn't there
      */
     sg.setStartRes(0);
@@ -116,4 +152,53 @@ public class AlignViewControllerTest
     assertEquals(0, seqCount);
     assertEquals(0, bs.cardinality());
   }
+
+  /**
+   * shameless copy of test data from findFeature for testing mark columns from
+   * highlight
+   */
+  @Test(groups = "Functional")
+  public void testSelectColumnsWithHighlight()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "seq1 aMMMaaaaaaaaaaaaaaaa\n" + "seq2 aaaMMMMMMMaaaaaaaaaa\n"
+                    + "seq3 aaaaaaaaaaMMMMMaaaaa\n"
+                    + "seq4 aaaaaaaaaaaaaaaaaaaa\n", FormatAdapter.PASTE);
+
+    SearchResultsI sr = new SearchResults();
+    SequenceI[] sqs = af.getViewport().getAlignment().getSequencesArray();
+    SequenceI seq1 = sqs[0];
+    SequenceI seq2 = sqs[1];
+    SequenceI seq3 = sqs[2];
+    SequenceI seq4 = sqs[3];
+
+    /*
+     * features start/end are base 1
+     */
+    sr.addResult(seq1, 2, 4);
+    sr.addResult(seq2, 4, 10);
+    sr.addResult(seq3, 11, 15);
+
+    /*
+     *  test Match/Find works first
+     */
+    Finder f = new Finder(af.getViewport().getAlignment(), null);
+    f.setFindAll(true);
+    f.setCaseSensitive(true);
+    f.find("M+");
+    assertEquals(
+            "Finder found different set of results to manually created SearchResults",
+            sr, f.getSearchResults());
+
+    /*
+     * now check simple mark columns from find operation
+     */
+    af.getViewport().setSearchResults(sr);
+    AlignViewControllerI avc = af.avc;
+
+    avc.markHighlightedColumns(false, false, false);
+    assertTrue("Didn't select highlighted columns", Arrays.deepEquals(af
+            .getViewport().getColumnSelection().getSelectedRanges()
+            .toArray(), new int[][] { { 1, 14 } }));
+  }
 }
index 6f3c7a9..95764d0 100644 (file)
@@ -24,8 +24,6 @@ import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
-import jalview.datamodel.SearchResults.Match;
-
 import org.testng.annotations.Test;
 
 public class MatchTest
@@ -34,17 +32,9 @@ public class MatchTest
   @Test(groups = { "Functional" })
   public void testToString()
   {
-    SequenceI seq = new Sequence("", "abcdefghijklm");
-    Match m = new SearchResults().new Match(seq, 3, 5);
-    assertEquals("2cde", m.toString());
-  }
-
-  @Test(groups = { "Functional" })
-  public void testGetCharacters()
-  {
-    SequenceI seq = new Sequence("", "abcdefghijklm");
-    Match m = new SearchResults().new Match(seq, 3, 5);
-    assertEquals("cde", m.getCharacters());
+    SequenceI seq = new Sequence("Seq1", "abcdefghijklm");
+    SearchResultMatchI m = new SearchResults().new Match(seq, 3, 5);
+    assertEquals("Seq1/3-5", m.toString());
   }
 
   @Test(groups = { "Functional" })
@@ -52,8 +42,8 @@ public class MatchTest
   {
     SequenceI seq1 = new Sequence("", "abcdefghijklm");
     SequenceI seq2 = new Sequence("", "abcdefghijklm");
-    SearchResults sr1 = new SearchResults();
-    SearchResults sr2 = new SearchResults();
+    SearchResultsI sr1 = new SearchResults();
+    SearchResultsI sr2 = new SearchResults();
 
     assertFalse(sr1.equals(null));
     assertFalse(sr1.equals(seq1));
@@ -72,7 +62,7 @@ public class MatchTest
     /*
      * same match but on different sequences - not equal
      */
-    SearchResults sr3 = new SearchResults();
+    SearchResultsI sr3 = new SearchResults();
     sr3.addResult(seq2, 1, 1);
     assertFalse(sr1.equals(sr3));
     assertFalse(sr3.equals(sr1));
index f98e3d3..6c6e36a 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.datamodel;
 
 import static org.testng.Assert.assertEquals;
index f9a0a4f..19e89d2 100644 (file)
@@ -25,8 +25,9 @@ import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 
-import jalview.datamodel.SearchResults.Match;
+import java.util.BitSet;
 
+import org.junit.Assert;
 import org.testng.annotations.Test;
 
 public class SearchResultsTest
@@ -35,39 +36,24 @@ public class SearchResultsTest
   @Test(groups = { "Functional" })
   public void testToString()
   {
-    SequenceI seq = new Sequence("", "abcdefghijklm");
-    SearchResults sr = new SearchResults();
+    SequenceI seq = new Sequence("Seq1", "abcdefghijklm");
+    SearchResultsI sr = new SearchResults();
     sr.addResult(seq, 1, 1);
-    assertEquals("0a", sr.toString());
+    assertEquals("[Seq1/1-1]", sr.toString());
     sr.addResult(seq, 3, 5);
-    assertEquals("0a2cde", sr.toString());
+    assertEquals("[Seq1/1-1, Seq1/3-5]", sr.toString());
 
-    seq = new Sequence("", "pqrstuvwxy");
+    seq = new Sequence("Seq2", "pqrstuvwxy");
     sr.addResult(seq, 6, 7);
-    assertEquals("0a2cde5uv", sr.toString());
-  }
-
-  @Test(groups = { "Functional" })
-  public void testGetCharacters()
-  {
-    SequenceI seq = new Sequence("", "abcdefghijklm");
-    SearchResults sr = new SearchResults();
-    sr.addResult(seq, 1, 1);
-    assertEquals("a", sr.getCharacters());
-    sr.addResult(seq, 3, 5);
-    assertEquals("acde", sr.getCharacters());
-
-    seq = new Sequence("", "pqrstuvwxy");
-    sr.addResult(seq, 6, 7);
-    assertEquals("acdeuv", sr.getCharacters());
+    assertEquals("[Seq1/1-1, Seq1/3-5, Seq2/6-7]", sr.toString());
   }
 
   @Test(groups = { "Functional" })
   public void testEquals()
   {
     SequenceI seq1 = new Sequence("", "abcdefghijklm");
-    SearchResults sr1 = new SearchResults();
-    SearchResults sr2 = new SearchResults();
+    SearchResultsI sr1 = new SearchResults();
+    SearchResultsI sr2 = new SearchResults();
 
     assertFalse(sr1.equals(null)); // null object
     assertFalse(sr1.equals(seq1)); // wrong type
@@ -76,7 +62,7 @@ public class SearchResultsTest
     assertTrue(sr2.equals(sr1)); // reflexive
 
     /*
-     * only one result is not empty
+     * if only one result is not empty
      */
     sr1.addResult(seq1, 1, 1);
     assertTrue(sr1.equals(sr1));
@@ -111,8 +97,8 @@ public class SearchResultsTest
   {
     SequenceI seq1 = new Sequence("", "abcdefghijklm");
     SequenceI seq2 = new Sequence("", "abcdefghijklm");
-    SearchResults sr1 = new SearchResults();
-    SearchResults sr2 = new SearchResults();
+    SearchResultsI sr1 = new SearchResults();
+    SearchResultsI sr2 = new SearchResults();
 
     sr1.addResult(seq1, 1, 1);
     sr2.addResult(seq2, 1, 1);
@@ -127,8 +113,8 @@ public class SearchResultsTest
   public void testEquals_orderDiffers()
   {
     SequenceI seq1 = new Sequence("", "abcdefghijklm");
-    SearchResults sr1 = new SearchResults();
-    SearchResults sr2 = new SearchResults();
+    SearchResultsI sr1 = new SearchResults();
+    SearchResultsI sr2 = new SearchResults();
 
     sr1.addResult(seq1, 1, 1);
     sr1.addResult(seq1, 2, 2);
@@ -145,8 +131,8 @@ public class SearchResultsTest
   public void testHashcode()
   {
     SequenceI seq1 = new Sequence("", "abcdefghijklm");
-    SearchResults sr1 = new SearchResults();
-    SearchResults sr2 = new SearchResults();
+    SearchResultsI sr1 = new SearchResults();
+    SearchResultsI sr2 = new SearchResults();
 
     /*
      * both empty
@@ -178,7 +164,7 @@ public class SearchResultsTest
   public void testMatchConstructor()
   {
     SequenceI seq1 = new Sequence("", "abcdefghijklm");
-    Match m = new SearchResults().new Match(seq1, 2, 5);
+    SearchResultMatchI m = new SearchResults().new Match(seq1, 2, 5);
     assertSame(seq1, m.getSequence());
     assertEquals(2, m.getStart());
     assertEquals(5, m.getEnd());
@@ -189,4 +175,87 @@ public class SearchResultsTest
     assertEquals(2, m.getStart());
     assertEquals(5, m.getEnd());
   }
+
+  /**
+   * test markColumns for creating column selections
+   */
+  @Test(groups = { "Functional" })
+  public void testMarkColumns()
+  {
+    int marked = 0;
+    SequenceI seq1 = new Sequence("", "abcdefghijklm");
+    SequenceI seq2 = new Sequence("", "abcdefghijklm");
+    SequenceGroup s1g=new SequenceGroup(), s2g=new SequenceGroup(), sallg=new SequenceGroup();
+    s1g.addSequence(seq1, false);
+    s2g.addSequence(seq2, false);
+    sallg.addSequence(seq1, false);
+    sallg.addSequence(seq2, false);
+    
+    SearchResultsI sr = new SearchResults();
+    BitSet bs = new BitSet();
+    
+    SearchResultMatchI srm = null;
+    srm = sr.addResult(seq1, 1, 1);
+    Assert.assertNotNull("addResult didn't return Match", srm);
+    srm = sr.addResult(seq2, 1, 2);
+    assertEquals("Sequence reference not set", seq2, srm.getSequence());
+    assertEquals("match start incorrect", 1, srm.getStart());
+    assertEquals("match end incorrect", 2, srm.getEnd());
+    
+    // set start/end range for groups to cover matches
+
+    s1g.setStartRes(0);
+    s1g.setEndRes(5);
+    s2g.setStartRes(0);
+    s2g.setEndRes(5);
+    sallg.setStartRes(0);
+    sallg.setEndRes(5);
+
+    /*
+     * just seq1
+     */
+    marked = sr.markColumns(s1g, bs);
+    // check the bitset cardinality before checking the return value
+    assertEquals("Didn't mark expected number", 1, bs.cardinality());
+    assertEquals("Didn't return count of number of bits marked", 1, marked);
+    assertTrue("Didn't mark expected position", bs.get(0));
+    // now check return value for marking the same again
+    assertEquals(
+            "Didn't count number of bits marked for existing marked set",
+            0,
+            sr.markColumns(s1g, bs));
+    bs.clear();
+    
+    /*
+     * just seq2
+     */
+    marked = sr.markColumns(s2g, bs);
+    assertEquals("Didn't mark expected number", 2, bs.cardinality());
+    assertEquals("Didn't return count of number of bits marked", 2, marked);
+    assertTrue("Didn't mark expected position (1)", bs.get(0));
+    assertTrue("Didn't mark expected position (2)", bs.get(1));
+    
+    /*
+     * both seq1 and seq2 
+     * should be same as seq2
+     */
+    BitSet allbs = new BitSet();
+    assertEquals(2, sr.markColumns(sallg, allbs));
+    assertEquals(bs, allbs);
+
+    // now check range selection
+
+    /*
+     * limit s2g to just the second column, sallg to the first column
+     */
+    s2g.setStartRes(1);
+    s2g.setEndRes(1);
+    sallg.setEndRes(0);
+    BitSet tbs = new BitSet();
+    assertEquals("Group start/end didn't select columns to mark",1, sr.markColumns(s2g, tbs));
+    assertEquals("Group start/end didn't select columns to mark", 1, sr.markColumns(sallg, tbs));
+    assertEquals(
+            "Didn't set expected number of columns in total for two successive marks",
+            2, tbs.cardinality());
+  }
 }
index 2ec824d..23812ea 100644 (file)
@@ -112,56 +112,83 @@ public class SequenceFeatureTest
     assertEquals(sf1.hashCode(), sf2.hashCode());
 
     // changing type breaks equals:
+    String restores = sf2.getType();
     sf2.setType("Type");
     assertFalse(sf1.equals(sf2));
+    sf2.setType(restores);
 
     // changing description breaks equals:
-    sf2.setType("type");
+    restores = sf2.getDescription();
     sf2.setDescription("Desc");
     assertFalse(sf1.equals(sf2));
+    sf2.setDescription(restores);
+
+    // changing score breaks equals:
+    float restoref = sf2.getScore();
+    sf2.setScore(12.4f);
+    assertFalse(sf1.equals(sf2));
+    sf2.setScore(restoref);
+
+    // NaN doesn't match a number
+    restoref = sf2.getScore();
+    sf2.setScore(Float.NaN);
+    assertFalse(sf1.equals(sf2));
+
+    // NaN matches NaN
+    sf1.setScore(Float.NaN);
+    assertTrue(sf1.equals(sf2));
+    sf1.setScore(restoref);
+    sf2.setScore(restoref);
 
     // changing start position breaks equals:
-    sf2.setDescription("desc");
+    int restorei = sf2.getBegin();
     sf2.setBegin(21);
     assertFalse(sf1.equals(sf2));
+    sf2.setBegin(restorei);
 
     // changing end position breaks equals:
-    sf2.setBegin(22);
+    restorei = sf2.getEnd();
     sf2.setEnd(32);
     assertFalse(sf1.equals(sf2));
+    sf2.setEnd(restorei);
 
     // changing feature group breaks equals:
-    sf2.setEnd(33);
+    restores = sf2.getFeatureGroup();
     sf2.setFeatureGroup("Group");
     assertFalse(sf1.equals(sf2));
+    sf2.setFeatureGroup(restores);
 
     // changing ID breaks equals:
-    sf2.setFeatureGroup("group");
+    restores = (String) sf2.getValue("ID");
     sf2.setValue("ID", "id2");
     assertFalse(sf1.equals(sf2));
+    sf2.setValue("ID", restores);
 
     // changing Name breaks equals:
-    sf2.setValue("ID", "id");
+    restores = (String) sf2.getValue("Name");
     sf2.setValue("Name", "Name");
     assertFalse(sf1.equals(sf2));
+    sf2.setValue("Name", restores);
 
     // changing Parent breaks equals:
-    sf2.setValue("Name", "name");
+    restores = (String) sf1.getValue("Parent");
     sf1.setValue("Parent", "Parent");
     assertFalse(sf1.equals(sf2));
+    sf1.setValue("Parent", restores);
 
     // changing strand breaks equals:
-    sf1.setValue("Parent", "parent");
+    restorei = sf2.getStrand();
     sf2.setStrand("-");
     assertFalse(sf1.equals(sf2));
+    sf2.setStrand(restorei == 1 ? "+" : "-");
 
     // changing phase breaks equals:
-    sf2.setStrand("+");
+    restores = sf1.getPhase();
     sf1.setPhase("2");
     assertFalse(sf1.equals(sf2));
+    sf1.setPhase(restores);
 
     // restore equality as sanity check:
-    sf1.setPhase("1");
     assertTrue(sf1.equals(sf2));
     assertTrue(sf2.equals(sf1));
     assertEquals(sf1.hashCode(), sf2.hashCode());
@@ -170,4 +197,24 @@ public class SequenceFeatureTest
     sf1.setStatus("new");
     assertTrue(sf1.equals(sf2));
   }
+
+  @Test(groups = { "Functional" })
+  public void testIsContactFeature()
+  {
+    SequenceFeature sf = new SequenceFeature("type", "desc", 22, 33, 12.5f,
+            "group");
+    assertFalse(sf.isContactFeature());
+    sf.setType("");
+    assertFalse(sf.isContactFeature());
+    sf.setType(null);
+    assertFalse(sf.isContactFeature());
+    sf.setType("Disulfide Bond");
+    assertTrue(sf.isContactFeature());
+    sf.setType("disulfide bond");
+    assertTrue(sf.isContactFeature());
+    sf.setType("Disulphide Bond");
+    assertTrue(sf.isContactFeature());
+    sf.setType("disulphide bond");
+    assertTrue(sf.isContactFeature());
+  }
 }
index 0ce0467..be95d6e 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.android;
 
 import static org.testng.Assert.assertEquals;
index 351f640..df161b7 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.android;
 
 import static org.testng.Assert.assertEquals;
index 00c52ed..dfe0e68 100644 (file)
@@ -35,6 +35,8 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry.Type;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.io.FileLoader;
@@ -347,4 +349,28 @@ public class AlignViewportTest
     af.getViewport().setGlobalColourScheme(cs);
     assertFalse(cs.conservationApplied());
   }
+
+  @Test(groups = { "Functional" })
+  public void testSetGetHasSearchResults()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", FormatAdapter.FILE);
+    SearchResultsI sr = new SearchResults();
+    SequenceI s1 = af.getViewport().getAlignment().getSequenceAt(0);
+
+    // create arbitrary range on first sequence
+    sr.addResult(s1, s1.getStart() + 10, s1.getStart() + 15);
+
+    // test set
+    af.getViewport().setSearchResults(sr);
+    // has -> true
+    assertTrue(af.getViewport().hasSearchResults());
+    // get == original
+    assertEquals(sr, af.getViewport().getSearchResults());
+
+    // set(null) results in has -> false
+
+    af.getViewport().setSearchResults(null);
+    assertFalse(af.getViewport().hasSearchResults());
+  }
 }
index ddf9a15..77aa0f6 100644 (file)
@@ -54,7 +54,8 @@ public class BioJsHTMLOutputTest
       {
         e.printStackTrace();
       }
-      bjsTemplate = BioJsHTMLOutput.getBioJsTemplateAsString();
+      bjsTemplate = HTMLOutput.readFileAsString(BioJsHTMLOutput
+              .getCurrentBJSTemplateFile());
       // System.out.println(bjsTemplate);
     } catch (IOException e)
     {
@@ -70,7 +71,7 @@ public class BioJsHTMLOutputTest
   {
     try
     {
-      BioJsHTMLOutput.refreshBioJSVersionsInfo(null);
+      BioJsHTMLOutput.refreshVersionInfo(null);
     } catch (URISyntaxException e)
     {
       AssertJUnit.fail("Expception occured while testing!");
@@ -85,7 +86,7 @@ public class BioJsHTMLOutputTest
     try
     {
       BioJsHTMLOutput
-              .refreshBioJSVersionsInfo(BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
+              .refreshVersionInfo(BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
       versions = BioJsHTMLOutput.getBioJsMSAVersions();
     } catch (URISyntaxException e)
     {
index a96a2a8..1392157 100644 (file)
@@ -35,7 +35,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_disulfideBond()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     sb.append("123456");
     SequenceFeature sf = new SequenceFeature("disulfide bond", "desc", 1,
             3, 1.2f, "group");
@@ -60,7 +60,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_status()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
             Float.NaN, "group");
     sf.setStatus("Confirmed");
@@ -73,7 +73,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_withScore()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
             "group");
 
@@ -106,7 +106,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_noScore()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
             Float.NaN, "group");
 
@@ -118,7 +118,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_clinicalSignificance()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
             Float.NaN, "group");
     sf.setValue("clinical_significance", "Benign");
@@ -131,7 +131,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_withScoreStatusClinicalSignificance()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
             "group");
     sf.setStatus("Confirmed");
@@ -148,7 +148,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_DescEqualsType()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL", "METAL", 1, 3,
             Float.NaN, "group");
 
@@ -167,7 +167,7 @@ public class SequenceAnnotationReportTest
   public void testAppendFeature_stripHtml()
   {
     SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     SequenceFeature sf = new SequenceFeature("METAL",
             "<html><body>hello<em>world</em></body></html>", 1, 3,
             Float.NaN, "group");
index 318ba3f..a02ca06 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.schemes;
 
 import static org.testng.AssertJUnit.assertEquals;
@@ -6,6 +26,7 @@ import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.datamodel.Profile;
 import jalview.datamodel.ProfileI;
+import jalview.datamodel.Profiles;
 
 import java.awt.Color;
 
@@ -23,13 +44,13 @@ public class ResidueColourSchemeTest
      * SR-T
      * SR-T
      */
-    ProfileI[] profiles = new ProfileI[4]; 
+    ProfileI[] profiles = new ProfileI[4];
     profiles[0] = new Profile(4, 0, 2, "AS");
     profiles[1] = new Profile(4, 0, 4, "R");
     profiles[2] = new Profile(4, 4, 0, "");
     profiles[3] = new Profile(4, 1, 2, "T");
     ResidueColourScheme rcs = new ResidueColourScheme();
-    rcs.setConsensus(profiles);
+    rcs.setConsensus(new Profiles(profiles));
     
     /*
      * no threshold
index 0d00169..66e0152 100644 (file)
@@ -104,7 +104,6 @@ public class AAStructureBindingModelTest
     pdbFiles[0] = new PDBEntry("1YCS", "A", Type.PDB, "INLINE1YCS");
     pdbFiles[1] = new PDBEntry("3A6S", "B", Type.PDB, "INLINE3A6S");
     pdbFiles[2] = new PDBEntry("1OOT", "A", Type.PDB, "INLINE1OOT");
-    String[][] chains = new String[3][];
     SequenceI[][] seqs = new SequenceI[3][];
     seqs[0] = new SequenceI[] { seq1a, seq1b };
     seqs[1] = new SequenceI[] { seq2 };
@@ -118,7 +117,7 @@ public class AAStructureBindingModelTest
     ssm.setMapping(new SequenceI[] { seq3 }, null, PDB_3,
             AppletFormatAdapter.PASTE);
 
-    testee = new AAStructureBindingModel(ssm, pdbFiles, seqs, chains, null)
+    testee = new AAStructureBindingModel(ssm, pdbFiles, seqs, null)
     {
       @Override
       public String[] getPdbFile()
@@ -140,6 +139,12 @@ public class AAStructureBindingModelTest
       public void highlightAtoms(List<AtomSpec> atoms)
       {
       }
+
+      @Override
+      public List<String> getChainNames()
+      {
+        return null;
+      }
     };
   }
 
index 2082963..d957b7c 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import static org.testng.Assert.assertEquals;
index 655aa2a..6d04661 100644 (file)
@@ -33,8 +33,8 @@ import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.SearchResults;
-import jalview.datamodel.SearchResults.Match;
+import jalview.datamodel.SearchResultMatchI;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -81,9 +81,9 @@ public class MappingUtilsTest
     /*
      * Check protein residue 12 maps to codon 5-7, 13 to codon 8-10
      */
-    SearchResults sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
+    SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
     assertEquals(1, sr.getResults().size());
-    Match m = sr.getResults().get(0);
+    SearchResultMatchI m = sr.getResults().get(0);
     assertEquals(seq1.getDatasetSequence(), m.getSequence());
     assertEquals(5, m.getStart());
     assertEquals(7, m.getEnd());
@@ -134,9 +134,9 @@ public class MappingUtilsTest
     /*
      * Check protein residue 8 maps to [6, 8, 9]
      */
-    SearchResults sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
+    SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
     assertEquals(2, sr.getResults().size());
-    Match m = sr.getResults().get(0);
+    SearchResultMatchI m = sr.getResults().get(0);
     assertEquals(seq1.getDatasetSequence(), m.getSequence());
     assertEquals(6, m.getStart());
     assertEquals(6, m.getEnd());
index 88fd1b9..e9e4628 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import static org.testng.Assert.assertFalse;
index c9a07a1..f4a0c97 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import static org.testng.Assert.assertEquals;
index f22a3b7..3f67c4c 100644 (file)
@@ -387,8 +387,8 @@ public class SiftsClientTest
               testSeq, testPDBId, "A");
       String expectedMappingOutput = "\nSequence ⟷ Structure mapping details\n"
               + "Method: SIFTS\n\n"
-              + "P00221 :  1 - 97 Maps to \n"
-              + "1A70|A :  51 - 147\n\n"
+              + "P00221 :  51 - 147 Maps to \n"
+              + "1A70|A :  1 - 97\n\n"
               + "P00221 AAYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDDQSFLD\n"
               + "       |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n"
               + "1A70|A AAYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDDQSFLD\n\n"
index fc799bb..3cfc2bb 100755 (executable)
@@ -1245,7 +1245,7 @@ and any path to a file to save to the file]]></string>
                                                                <string><![CDATA[664]]></string>
                                                        </property>
                                                        <property name="sourceName">
-                                                               <string><![CDATA[Jmol-14.2.14_2015.06.11.jar]]></string>
+                                                               <string><![CDATA[Jmol-14.6.4_2016.10.26.jar]]></string>
                                                        </property>
                                                        <property name="overrideUnixPermissions">
                                                                <boolean>false</boolean>
@@ -1263,7 +1263,7 @@ and any path to a file to save to the file]]></string>
                                                                <boolean>true</boolean>
                                                        </property>
                                                        <property name="destinationName">
-                                                               <string><![CDATA[Jmol-14.2.14_2015.06.11.jar]]></string>
+                                                               <string><![CDATA[Jmol-14.6.4_2016.10.26.jar]]></string>
                                                        </property>
                                                        <property name="fileSize">
                                                                <long>5417196</long>
@@ -3846,7 +3846,7 @@ Press "Done" to quit the installer.]]></string>
                                                                                                <boolean>true</boolean>
                                                                                        </property>
                                                                                        <property name="bundledVM">
-                                                                                               <string><![CDATA[OracleJRE8u5_Macosx.vm]]></string>
+                                                                                               <string><![CDATA[OracleJRE180u92_macosx.vm]]></string>
                                                                                        </property>
                                                                                        <property name="withoutVmSearchOption">
                                                                                                <short>10</short>
@@ -3883,7 +3883,7 @@ Press "Done" to quit the installer.]]></string>
                                                                                                <boolean>true</boolean>
                                                                                        </property>
                                                                                        <property name="bundledVM">
-                                                                                               <string><![CDATA[SunJRE170_03Win32.vm]]></string>
+                                                                                               <string><![CDATA[OracleJRE8u92_windows(x86).vm]]></string>
                                                                                        </property>
                                                                                        <property name="withoutVmSearchOption">
                                                                                                <short>10</short>
@@ -3954,10 +3954,10 @@ Press "Done" to quit the installer.]]></string>
                                                                                                <boolean>true</boolean>
                                                                                        </property>
                                                                                        <property name="buildWithVM">
-                                                                                               <boolean>true</boolean>
+                                                                                               <boolean>false</boolean>
                                                                                        </property>
                                                                                        <property name="bundledVM">
-                                                                                               <string><![CDATA[JRE16_16002HPUX11PA-RISC.vm]]></string>
+                                                                                               <string><![CDATA[JRE16_16010HPUXPA-RISC.vm]]></string>
                                                                                        </property>
                                                                                        <property name="withoutVmSearchOption">
                                                                                                <short>10</short>
@@ -3994,7 +3994,7 @@ Press "Done" to quit the installer.]]></string>
                                                                                                <boolean>true</boolean>
                                                                                        </property>
                                                                                        <property name="bundledVM">
-                                                                                               <string><![CDATA[ORACLEJRE7u60_linux32.vm]]></string>
+                                                                                               <string><![CDATA[OracleJRE180u92_Linux32.vm]]></string>
                                                                                        </property>
                                                                                        <property name="withoutVmSearchOption">
                                                                                                <short>10</short>
@@ -4102,7 +4102,7 @@ Press "Done" to quit the installer.]]></string>
                                                                                                <boolean>true</boolean>
                                                                                        </property>
                                                                                        <property name="bundledVM">
-                                                                                               <string><![CDATA[ORACLEJRE7u60_linux32.vm]]></string>
+                                                                                               <string><![CDATA[OracleJRE180u92_Linux32.vm]]></string>
                                                                                        </property>
                                                                                        <property name="withoutVmSearchOption">
                                                                                                <short>10</short>
@@ -4173,7 +4173,7 @@ Press "Done" to quit the installer.]]></string>
                                                                                                <boolean>true</boolean>
                                                                                        </property>
                                                                                        <property name="bundledVM">
-                                                                                               <string><![CDATA[OracleJRE8u5_windows(x64).vm]]></string>
+                                                                                               <string><![CDATA[OracleJRE180u92_windows(x64).vm]]></string>
                                                                                        </property>
                                                                                        <property name="withoutVmSearchOption">
                                                                                                <short>10</short>
@@ -5270,7 +5270,7 @@ Press "Done" to quit the installer.]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.installer.options.valid.vm.list]]></string>
-                                               <string><![CDATA[1.7+]]></string>
+                                               <string><![CDATA[1.8+]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.project.build.last.date]]></string>
@@ -5366,7 +5366,7 @@ Press "Done" to quit the installer.]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.installer.options.platform.macosx.vm.version]]></string>
-                                               <string><![CDATA[1.7+]]></string>
+                                               <string><![CDATA[1.8+]]></string>
                                        </method>
                                        <method name="put">
                                                <string><![CDATA[com.zerog.ia.build.platform.java.novm]]></string>