Merge branch 'develop' into Release_2_9_0b1_Branch
authorJim Procter <jprocter@issues.jalview.org>
Mon, 5 Oct 2015 12:03:44 +0000 (13:03 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Mon, 5 Oct 2015 12:03:44 +0000 (13:03 +0100)
JAL-1894 update release branch from develop

39 files changed:
examples/appletParameters.html
examples/applets.html
examples/estrogenReceptorProtein_frag.fa
examples/exampleFeatures.txt
help/html/features/columnFilterByAnnotation.html
help/html/releases.html
src/jalview/api/ComplexAlignFile.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AlignViewport.java
src/jalview/appletgui/CutAndPasteTransfer.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AppJmol.java
src/jalview/gui/CutAndPasteTransfer.java
src/jalview/gui/Desktop.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/PDBSearchPanel.java
src/jalview/gui/SeqPanel.java
src/jalview/gui/SplitFrame.java
src/jalview/gui/StructureChooser.java
src/jalview/io/FeaturesFile.java
src/jalview/io/FileLoader.java
src/jalview/io/HtmlFile.java
src/jalview/io/HtmlSvgOutput.java
src/jalview/io/IdentifyFile.java
src/jalview/io/JSONFile.java
src/jalview/jbgui/GPDBSearchPanel.java
src/jalview/jbgui/GSplitFrame.java
src/jalview/jbgui/GStructureChooser.java
src/jalview/json/binding/biojson/v1/ColourSchemeMapper.java [new file with mode: 0644]
src/jalview/json/binding/biojson/v1/JalviewBioJsColorSchemeMapper.java [deleted file]
src/jalview/util/ParseHtmlBodyAndLinks.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/ws/jws1/SeqSearchWSThread.java
src/jalview/ws/uimodel/PDBRestRequest.java
test/jalview/io/FeaturesFileTest.java [new file with mode: 0644]
test/jalview/io/JSONFileTest.java
test/jalview/util/ParseHtmlBodyAndLinksTest.java [new file with mode: 0644]
test/jalview/ws/dbsources/PDBRestClientTest.java

index ed822d3..50546a3 100644 (file)
@@ -118,6 +118,14 @@ the applet can be interacted with <em>via</em> its
             <td>Default is no colour.</td>
           </tr>
           <tr> 
+            <td>defaultColourNuc</td>
+            <td>A colour scheme (from the list above) to apply to Nucleotide alignments</td><td>This overrides defaultColour if it is specified.</td>
+          </tr>
+          <tr> 
+            <td>defaultColourProt</td>
+            <td>A colour scheme (from the list above) to apply to Peptide alignments</td><td>This overrides defaultColour if it is specified.</td>
+          </tr>
+          <tr> 
             <td>userDefinedColour</td>
             <td><p><em>Example:</em><br>
                 D,E=red; K,R,H=0022FF; c=yellow</p></td>
index 32203f2..852a446 100644 (file)
@@ -187,7 +187,8 @@ Try out JalviewLite by pressing one of the buttons below.<br/>
 <param name="windowWidth" value="800"/>
 <param name="showAnnotation" value="true"/>
 <param name="showSequenceLogo" value="true"/>
-<param name="defaultColour" value="Purine/Pyrimidine"/>
+<param name="defaultColourNuc" value="Purine/Pyrimidine"/>
+<param name="defaultColourProt" value="Clustal"/>
    <param name="APPLICATION_URL"
      value="http://www.jalview.org/services/launchApp"/>
 </applet>
index cb3c37e..c9e31aa 100644 (file)
@@ -1,14 +1,8 @@
->UNIPROT|Q7LCB3/249-274
----SLEHTLPVNRETLKRKVSGNRCASPV----------
->UNIPROT|Q9VSE9/175-200
----GSGTSGGNGGGGGGGTSGGNATNASA----------
 >UNIPROT|Q9IBD5/371-408
 EGHHNYLCAGRNDCIVDKIRRKNCPACRLRKCYQAGMI-
 >UNIPROT|Q9YGV9/522-559
 EGKQKYLCASINDCTIDKLRRKNCPSCRLKRCFAAGMT-
 >UNIPROT|Q90ZM7/97-134
 EGQHNYLCAGRNDCIIDKIRRKNCPACRLRKCIQAGMT-
->UNIPROT|Q91445/24-61
-EGKQKYLCASRNDCTIDKFRRKNCPSCRLRKCYEAGMT-
 >UNIPROT|Q90ZM8/198-236
 QGHNDYMCPATNQCTIDRNRRKSCQACRLRKCYEVGMVK
index ab2dcff..f0b13ab 100755 (executable)
@@ -24,7 +24,7 @@ BETA-BULGE    1dc451
 Pfam   dc206a
 PHOSPHORYLATION (S)    b974a5
 PHOSPHORYLATION (Y)    7d3881
-Cath   93b1d2
+Cath   93b1d1
 ASX-TURN-IR    4ccc6e
 BETA-BULGE-LOOP-5      4066da
 CATMAT-4       4dc465
@@ -44,70 +44,70 @@ BETA-TURN-IIL       8b5b50
 ST-MOTIF       ac25a1
 
 STARTGROUP     uniprot
-Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      39      39      METAL
-Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      44      44      METAL
-Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      47      47      METAL
-Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      77      77      METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      39      39      METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      44      44      METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      47      47      METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAA       -1      77      77      METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 8_8</a></html> FER_CAPAA       -1      8       83      Pfam
 Ferredoxin_fold Status: True Positive  FER_CAPAA       -1      3       93      Cath
-Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      86      86      METAL
-Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      91      91      METAL
-Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      94      94      METAL
-Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      124     124     METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      86      86      METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      91      91      METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      94      94      METAL
+Iron-sulfur (2Fe-2S)   FER_CAPAN       -1      124     124     METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 55_13</a></html>       FER_CAPAN       -1      55      130     Pfam
 Ferredoxin_fold Status: True Positive  FER_CAPAN       -1      45      140     Cath
-Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      86      86      METAL
-Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      91      91      METAL
-Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      94      94      METAL
-Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      124     124     METAL
+Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      86      86      METAL
+Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      91      91      METAL
+Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      94      94      METAL
+Iron-sulfur (2Fe-2S)   FER1_SOLLC      -1      124     124     METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 55_13</a></html>       FER1_SOLLC      -1      55      130     Pfam
 Ferredoxin_fold Status: True Positive  FER1_SOLLC      -1      45      140     Cath
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 55_13</a></html>       Q93XJ9_SOLTU    -1      55      130     Pfam
 Ferredoxin_fold Status: True Positive  Q93XJ9_SOLTU    -1      45      140     Cath
-Iron-sulfur (2Fe-2S)   FER1_PEA        -1      91      91      METAL
-Iron-sulfur (2Fe-2S)   FER1_PEA        -1      96      96      METAL
-Iron-sulfur (2Fe-2S)   FER1_PEA        -1      99      99      METAL
-Iron-sulfur (2Fe-2S)   FER1_PEA        -1      129     129     METAL
+Iron-sulfur (2Fe-2S)   FER1_PEA        -1      91      91      METAL
+Iron-sulfur (2Fe-2S)   FER1_PEA        -1      96      96      METAL
+Iron-sulfur (2Fe-2S)   FER1_PEA        -1      99      99      METAL
+Iron-sulfur (2Fe-2S)   FER1_PEA        -1      129     129     METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 60_13</a></html>       FER1_PEA        -1      60      135     Pfam
 Ferredoxin_fold Status: True Positive  FER1_PEA        -1      50      145     Cath
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 63_13</a></html>       Q7XA98_TRIPR    -1      63      138     Pfam
 Ferredoxin_fold Status: True Positive  Q7XA98_TRIPR    -1      53      148     Cath
-Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      90      90      METAL
-Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      95      95      METAL
-Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      98      98      METAL
-Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      128     128     METAL
+Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      90      90      METAL
+Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      95      95      METAL
+Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      98      98      METAL
+Iron-sulfur (2Fe-2S)   FER1_MESCR      -1      128     128     METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 59_13</a></html>       FER1_MESCR      -1      59      134     Pfam
 Ferredoxin_fold Status: True Positive  FER1_MESCR      -1      49      144     Cath
-Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      89      89      METAL
-Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      94      94      METAL
-Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      97      97      METAL
-Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      127     127     METAL
+Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      89      89      METAL
+Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      94      94      METAL
+Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      97      97      METAL
+Iron-sulfur (2Fe-2S)   FER1_SPIOL      -1      127     127     METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 58_13</a></html>       FER1_SPIOL      -1      58      133     Pfam
 Ferredoxin_fold Status: True Positive  FER1_SPIOL      -1      48      143     Cath
-Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      39      39      METAL
-Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      44      44      METAL
-Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      47      47      METAL
-Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      77      77      METAL
+Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      39      39      METAL
+Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      44      44      METAL
+Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      47      47      METAL
+Iron-sulfur (2Fe-2S)   FER3_RAPSA      -1      77      77      METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 8_8</a></html> FER3_RAPSA      -1      8       83      Pfam
 Ferredoxin_fold Status: True Positive  FER3_RAPSA      -1      3       93      Cath
-Iron-sulfur (2Fe-2S)   FER_BRANA       -1      39      39      METAL
-Iron-sulfur (2Fe-2S)   FER_BRANA       -1      44      44      METAL
-Iron-sulfur (2Fe-2S)   FER_BRANA       -1      47      47      METAL
-Iron-sulfur (2Fe-2S)   FER_BRANA       -1      77      77      METAL
+Iron-sulfur (2Fe-2S)   FER_BRANA       -1      39      39      METAL
+Iron-sulfur (2Fe-2S)   FER_BRANA       -1      44      44      METAL
+Iron-sulfur (2Fe-2S)   FER_BRANA       -1      47      47      METAL
+Iron-sulfur (2Fe-2S)   FER_BRANA       -1      77      77      METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 8_8</a></html> FER_BRANA       -1      8       83      Pfam
 Ferredoxin_fold Status: True Positive  FER_BRANA       -1      2       96      Cath
-Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      91      91      METAL
-Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      96      96      METAL
-Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      99      99      METAL
-Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      129     129     METAL
+Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      91      91      METAL
+Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      96      96      METAL
+Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      99      99      METAL
+Iron-sulfur (2Fe-2S)   FER2_ARATH      -1      129     129     METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 60_13</a></html>       FER2_ARATH      -1      60      135     Pfam
 Ferredoxin_fold Status: True Positive  FER2_ARATH      -1      50      145     Cath
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 60_11</a></html>       Q93Z60_ARATH    -1      60      118     Pfam
 Ferredoxin_fold Status: True Positive  Q93Z60_ARATH    -1      52      118     Cath
-Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      91      91      METAL
-Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      96      96      METAL
-Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      99      99      METAL
-Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      129     129     METAL
+Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      91      91      METAL
+Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      96      96      METAL
+Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      99      99      METAL
+Iron-sulfur (2Fe-2S)   FER1_MAIZE      -1      129     129     METAL
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 60_13</a></html>       FER1_MAIZE      -1      60      135     Pfam
 Ferredoxin_fold Status: True Positive  FER1_MAIZE      -1      50      145     Cath
 <html>Fer2 Status: True Positive <a href="http://pfam.sanger.ac.uk/family/PF00111">Pfam 52_12</a></html>       O80429_MAIZE    -1      52      127     Pfam
index 128b478..8840b18 100644 (file)
@@ -37,8 +37,8 @@
   </p>
   <table>
     <tr>
-      <td><img src="annotationColumnSelectionWithSM.gif"></td>
-      <td><img src="annotationColumnSelectionWithoutSM.gif"></td>
+      <td><img src="AnnotationColumnSelectionWithSM.gif"></td>
+      <td><img src="AnnotationColumnSelectionWithoutSM.gif"></td>
     </tr>
   </table>
 
index 1aba54c..6f4f159 100755 (executable)
       <td width="60" nowrap>
         <div align="center">
           <strong><a name="Jalview.2.9.0b1">2.9.0b1</a><br />
-            <em>29/09/2015</em></strong>
+            <em>6/10/2015</em></strong>
         </div>
       </td>
       <td>
-        <div align="center"></div>
+      <em>General</em>
+      <ul>
+            <li>Updated Spanish translations of localized text for 2.9</li>
+      </ul>
+      <em>Application</em><ul>
+      <!-- <li>cDNA/Protein splitframe window geometry preserved in Jalview projects</li>-->
+      <li>Signed OSX InstallAnywhere installer</li></ul>
+        <em>Applet</em>
+        <ul><li>Split frame example added to applet examples page</li>
+            </ul>
       </td>
       <td>
         <div align="left">
+        <em>General</em>
           <ul>
             <li>Mapping of cDNA to protein in split frames incorrect when sequence start > 1</li>
-            <li>Split frame example added to applet examples page</li>
-            <li>Applet with Jmol examples not loading correctly</li>
-            <li>Incorrect warning on deleting selected columns</li>
-            <li>Annotations incorrectly rendered after BioJS export and reimport</li>
-            <li>Incorrect sequence limits after Fetch DB References with 'trim retrieved sequences'</li>
-            <li>Spanish translations of localized text - updates needed for 2.9</li>
-            <li>Provide signed OSX InstallAnywhere installer</li>
+            <li>Broken images in filter column by annotation dialog documentation</li>
+            <li>Feature colours not parsed from features file</li>
+            <li>Exceptions and incomplete link URLs recovered when loading a features file containing HTML tags in feature description</li>
+            
           </ul>
+      <em>Application</em><ul>
+            <li>Annotations corrupted after BioJS export and reimport</li>
+            <li>Incorrect sequence limits after Fetch DB References with 'trim retrieved sequences'</li>
+            <li>Incorrect warning about deleting all data when deleting selected columns</li>
+            <li>Patch to build system for shipping properly signed JNLP templates for webstart launch</li>
+            <li>EMBL-PDBe fetcher/viewer dialogs do not offer unreleased structures for download or viewing</li>
+            <li>Tab/space/return keystroke operation of EMBL-PDBe fetcher/viewer dialogs works correctly</li>
+            <li>Disabled 'minimise' button on Jalview windows running on OSX to workaround redraw hang bug</li>
+            <li>Split cDNA/Protein view position and geometry not recovered from jalview project</li>
+            <li>Initial enabled/disabled state of annotation menu sorter 'show autocalculated first/last' corresponds to alignment view</li>
+            </ul>
+      <em>Applet</em><ul>
+            <li>Reorder sequences mirrored in cDNA/Protein split frame</li>
+            <li>Applet with Jmol examples not loading correctly</li>
+            </ul>
         </div>
       </td>
     </tr>
index 4349382..8ad2ea7 100644 (file)
@@ -22,7 +22,6 @@ package jalview.api;
 
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.ColourSchemeI;
 
 /**
  * This interface should be implemented by complex file parser with the ability
@@ -44,7 +43,7 @@ public interface ComplexAlignFile
    * 
    * @return
    */
-  public ColourSchemeI getColourScheme();
+  public String getGlobalColourScheme();
 
   /**
    * Retrieves the Column selection/hidden column from a complex file parser
index c3c23c2..ea5fd5a 100644 (file)
@@ -1752,9 +1752,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
               viewport, complement);
       complement.getAlignment().moveSelectedSequencesByOne(mappedSelection,
               up ? null : complement.getHiddenRepSequences(), up);
-      // TODO need to trigger a repaint of the complementary panel - how?
-      // would prefer to handle in SplitFrame but it is not overriding key
-      // listener chiz
+      getSplitFrame().getComplement(this).alignPanel.paintAlignment(true);
     }
   }
 
index f8355c3..9256cfc 100644 (file)
@@ -187,8 +187,13 @@ public class AlignViewport extends AlignmentViewport implements
 
     if (applet != null)
     {
-      String colour = applet.getParameter("defaultColour");
-
+      String colour = al.isNucleotide() ? applet
+              .getParameter("defaultColourNuc") : applet
+              .getParameter("defaultColourProt");
+      if (colour == null)
+      {
+        colour = applet.getParameter("defaultColour");
+      }
       if (colour == null)
       {
         colour = applet.getParameter("userDefinedColour");
index 31603b8..b108029 100644 (file)
@@ -33,6 +33,7 @@ import jalview.io.FileParse;
 import jalview.io.IdentifyFile;
 import jalview.io.NewickFile;
 import jalview.io.TCoffeeScoreFile;
+import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.TCoffeeColourScheme;
 import jalview.util.MessageManager;
@@ -259,12 +260,18 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
                   .getHiddenSequences();
           boolean showSeqFeatures = ((ComplexAlignFile) source)
                   .isShowSeqFeatures();
-          ColourSchemeI cs = ((ComplexAlignFile) source).getColourScheme();
+          String colourSchemeName = ((ComplexAlignFile) source)
+                  .getGlobalColourScheme();
           af = new AlignFrame(al, hiddenSeqs, colSel,
                   alignFrame.viewport.applet, "Cut & Paste input - "
                           + format, false);
           af.getAlignViewport().setShowSequenceFeatures(showSeqFeatures);
-          af.changeColour(cs);
+          ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+                  colourSchemeName, al);
+          if (cs != null)
+          {
+            af.changeColour(cs);
+          }
         }
         else
         {
index d559d17..9aac56d 100644 (file)
@@ -1072,7 +1072,7 @@ public class AlignViewport extends AlignmentViewport implements
       // TODO would like next line without cast but needs more refactoring...
       final AlignmentPanel complementPanel = ((AlignViewport) getCodingComplement())
               .getAlignPanel();
-      complementPanel.setFollowingComplementScroll(true);
+      complementPanel.setDontScrollComplement(true);
       complementPanel.scrollToCentre(sr, verticalOffset);
     }
   }
index 9fbe5d2..e9ac7f3 100644 (file)
@@ -99,7 +99,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * Flag set while scrolling to follow complementary cDNA/protein scroll. When
    * true, suppresses invoking the same method recursively.
    */
-  private boolean followingComplementScroll;
+  private boolean dontScrollComplement;
 
   /**
    * Creates a new AlignmentPanel object.
@@ -732,7 +732,14 @@ public class AlignmentPanel extends GAlignmentPanel implements
       x = 0;
     }
 
+    /*
+     * each scroll adjustment triggers adjustmentValueChanged, which resets the
+     * 'do not scroll complement' flag; ensure it is the same for both
+     * operations
+     */
+    boolean flag = isDontScrollComplement();
     hscroll.setValues(x, hextent, 0, width);
+    setDontScrollComplement(flag);
     vscroll.setValues(y, vextent, 0, height);
   }
 
@@ -831,9 +838,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
      * If there is one, scroll the (Protein/cDNA) complementary alignment to
      * match, unless we are ourselves doing that.
      */
-    if (isFollowingComplementScroll())
+    if (isDontScrollComplement())
     {
-      setFollowingComplementScroll(false);
+      setDontScrollComplement(false);
     }
     else
     {
@@ -880,6 +887,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
     hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
     validate();
 
+    /*
+     * set scroll bar positions; first suppress this being 'followed' in any
+     * complementary split pane
+     */
+    setDontScrollComplement(true);
+
     if (av.getWrapAlignment())
     {
       int maxwidth = av.getAlignment().getWidth();
@@ -1789,17 +1802,17 @@ public class AlignmentPanel extends GAlignmentPanel implements
   }
 
   /**
-   * Set a flag to say we are scrolling to follow a (cDNA/protein) complement.
+   * Set a flag to say do not scroll any (cDNA/protein) complement.
    * 
    * @param b
    */
-  protected void setFollowingComplementScroll(boolean b)
+  protected void setDontScrollComplement(boolean b)
   {
-    this.followingComplementScroll = b;
+    this.dontScrollComplement = b;
   }
 
-  protected boolean isFollowingComplementScroll()
+  protected boolean isDontScrollComplement()
   {
-    return this.followingComplementScroll;
+    return this.dontScrollComplement;
   }
 }
index 55d5f8c..9bd729f 100644 (file)
@@ -383,6 +383,7 @@ public class AppJmol extends StructureViewerBase
       command = "";
     }
     jmb.evalStateCommand(command);
+    jmb.evalStateCommand("set hoverDelay=0.1");
     jmb.setFinishedInit(true);
   }
 
index 9c5651a..417c509 100644 (file)
@@ -35,6 +35,7 @@ import jalview.io.IdentifyFile;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.jbgui.GCutAndPasteTransfer;
+import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.schemes.ColourSchemeI;
 import jalview.util.MessageManager;
 
@@ -262,14 +263,20 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
                   .getHiddenSequences();
           boolean showSeqFeatures = ((ComplexAlignFile) source)
                   .isShowSeqFeatures();
-          ColourSchemeI cs = ((ComplexAlignFile) source).getColourScheme();
+          String colourSchemeName = ((ComplexAlignFile) source)
+                  .getGlobalColourScheme();
           FeaturesDisplayedI fd = ((ComplexAlignFile) source)
                   .getDisplayedFeatures();
           af = new AlignFrame(al, hiddenSeqs, colSel,
                   AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
           af.getViewport().setShowSequenceFeatures(showSeqFeatures);
           af.getViewport().setFeaturesDisplayed(fd);
-          af.changeColour(cs);
+          ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+                  colourSchemeName, al);
+          if (cs != null)
+          {
+            af.changeColour(cs);
+          }
         }
         else
         {
index 5c45232..145870a 100644 (file)
@@ -33,6 +33,7 @@ import jalview.jbgui.GStructureViewer;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.ImageMaker;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.params.ParamManager;
 
@@ -305,6 +306,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     boolean showjconsole = jalview.bin.Cache.getDefault(
             "SHOW_JAVA_CONSOLE", false);
     desktop = new MyDesktopPane(selmemusage);
+    if (Platform.isAMac())
+    {
+      desktop.setDoubleBuffered(false);
+    }
     showMemusage.setSelected(selmemusage);
     desktop.setBackground(Color.white);
     getContentPane().setLayout(new BorderLayout());
@@ -750,8 +755,13 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     frame.setResizable(resizable);
     frame.setMaximizable(resizable);
     frame.setIconifiable(resizable);
-    frame.setFrameIcon(null);
-
+    if (Platform.isAMac())
+    {
+      frame.setIconifiable(false);
+      frame.setFrameIcon(null);
+      // frame.setDesktopIcon(null);
+      frame.setDoubleBuffered(false);
+    }
     if (frame.getX() < 1 && frame.getY() < 1)
     {
       frame.setLocation(xOffset * openFrameCount, yOffset
@@ -2933,7 +2943,11 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   }
 
   /**
-   * Explode the views in the given frame into separate AlignFrame windows.
+   * Explode the views in the given SplitFrame into separate SplitFrame windows.
+   * This respects (remembers) any previous 'exploded geometry' i.e. the size
+   * and location last time the view was expanded (if any). However it does not
+   * remember the split pane divider location - this is set to match the
+   * 'exploding' frame.
    * 
    * @param sf
    */
@@ -2962,27 +2976,39 @@ public class Desktop extends jalview.jbgui.GDesktop implements
        * AlignmentPanel objects, including their AlignmentViewports, so the
        * cdna/protein relationships between the viewports is carried over to the
        * new split frames.
+       * 
+       * explodedGeometry holds the (x, y) position of the previously exploded
+       * SplitFrame, and the (width, height) of the AlignFrame component
        */
       AlignmentPanel topPanel = (AlignmentPanel) topPanels.get(i);
       AlignFrame newTopFrame = new AlignFrame(topPanel);
-      newTopFrame.setSize(new Dimension(AlignFrame.DEFAULT_WIDTH,
-              AlignFrame.DEFAULT_HEIGHT));
+      newTopFrame.setSize(oldTopFrame.getSize());
       newTopFrame.setVisible(true);
+      Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
+              .getExplodedGeometry();
+      if (geometry != null)
+      {
+        newTopFrame.setSize(geometry.getSize());
+      }
+
       AlignmentPanel bottomPanel = (AlignmentPanel) bottomPanels.get(i);
       AlignFrame newBottomFrame = new AlignFrame(bottomPanel);
-      newBottomFrame.setSize(new Dimension(AlignFrame.DEFAULT_WIDTH,
-              AlignFrame.DEFAULT_HEIGHT));
+      newBottomFrame.setSize(oldBottomFrame.getSize());
       newBottomFrame.setVisible(true);
+      geometry = ((AlignViewport) bottomPanel.getAlignViewport())
+              .getExplodedGeometry();
+      if (geometry != null)
+      {
+        newBottomFrame.setSize(geometry.getSize());
+      }
+
       topPanel.av.setGatherViewsHere(false);
       bottomPanel.av.setGatherViewsHere(false);
       JInternalFrame splitFrame = new SplitFrame(newTopFrame,
               newBottomFrame);
-      // either panel may hold previous exploded frame geometry
-      Rectangle geometry = ((AlignViewport) topPanel.getAlignViewport())
-              .getExplodedGeometry();
       if (geometry != null)
       {
-        splitFrame.setBounds(geometry);
+        splitFrame.setLocation(geometry.getLocation());
       }
       Desktop.addInternalFrame(splitFrame, sf.getTitle(), -1, -1);
     }
@@ -3005,10 +3031,18 @@ public class Desktop extends jalview.jbgui.GDesktop implements
    */
   public void gatherViews(GSplitFrame source)
   {
+    /*
+     * special handling of explodedGeometry for a view within a SplitFrame: - it
+     * holds the (x, y) position of the enclosing SplitFrame, and the (width,
+     * height) of the AlignFrame component
+     */
     AlignFrame myTopFrame = (AlignFrame) source.getTopFrame();
     AlignFrame myBottomFrame = (AlignFrame) source.getBottomFrame();
-    myTopFrame.viewport.setExplodedGeometry(source.getBounds());
-    myBottomFrame.viewport.setExplodedGeometry(source.getBounds());
+    myTopFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
+            source.getY(), myTopFrame.getWidth(), myTopFrame.getHeight()));
+    myBottomFrame.viewport.setExplodedGeometry(new Rectangle(source.getX(),
+            source.getY(), myBottomFrame.getWidth(), myBottomFrame
+                    .getHeight()));
     myTopFrame.viewport.setGatherViewsHere(true);
     myBottomFrame.viewport.setGatherViewsHere(true);
     String topViewId = myTopFrame.viewport.getSequenceSetId();
@@ -3033,10 +3067,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
             gatherThis = true;
             topPanel.av.setGatherViewsHere(false);
             bottomPanel.av.setGatherViewsHere(false);
-            // both panels refer to the same split frame geometry
-            Rectangle position = sf.getBounds();
-            topPanel.av.setExplodedGeometry(position);
-            bottomPanel.av.setExplodedGeometry(position);
+            topPanel.av.setExplodedGeometry(new Rectangle(sf.getLocation(),
+                    topFrame.getSize()));
+            bottomPanel.av.setExplodedGeometry(new Rectangle(sf
+                    .getLocation(), bottomFrame.getSize()));
             myTopFrame.addAlignmentPanel(topPanel, false);
             myBottomFrame.addAlignmentPanel(bottomPanel, false);
           }
index 0319e60..389a6a3 100644 (file)
@@ -1092,15 +1092,26 @@ public class Jalview2XML
       view.setViewName(av.viewName);
       view.setGatheredViews(av.isGatherViewsHere());
 
-      Rectangle position = ap.av.getExplodedGeometry();
-      if (position == null)
+      Rectangle size = ap.av.getExplodedGeometry();
+      Rectangle position = size;
+      if (size == null)
       {
-        position = ap.alignFrame.getBounds();
+        size = ap.alignFrame.getBounds();
+        if (av.getCodingComplement() != null)
+        {
+          position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
+                  .getBounds();
+        }
+        else
+        {
+          position = size;
+        }
       }
       view.setXpos(position.x);
       view.setYpos(position.y);
-      view.setWidth(position.width);
-      view.setHeight(position.height);
+
+      view.setWidth(size.width);
+      view.setHeight(size.height);
 
       view.setStartRes(av.startRes);
       view.setStartSeq(av.startSeq);
@@ -2453,6 +2464,11 @@ public class Jalview2XML
     int width = (int) dnaFrame.getBounds().getWidth();
     int height = (int) (dnaFrame.getBounds().getHeight()
             + proteinFrame.getBounds().getHeight() + 50);
+
+    /*
+     * SplitFrame location is saved to both enclosed frames
+     */
+    splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
     Desktop.addInternalFrame(splitFrame, title, width, height);
 
     /*
index 4c89f12..cef9ddd 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
index 3d43d35..52c3c46 100644 (file)
@@ -680,7 +680,7 @@ public class SeqPanel extends JPanel implements MouseListener,
        * 
        * @see AlignmentPanel#adjustmentValueChanged
        */
-      ap.setFollowingComplementScroll(true);
+      ap.setDontScrollComplement(true);
       if (ap.scrollToPosition(results, false))
       {
         seqCanvas.revalidate();
index 4e2187e..a6c7bb8 100644 (file)
@@ -26,6 +26,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.jbgui.GAlignFrame;
 import jalview.jbgui.GSplitFrame;
 import jalview.structure.StructureSelectionManager;
+import jalview.util.Platform;
 import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Component;
@@ -37,12 +38,15 @@ import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.beans.PropertyVetoException;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import javax.swing.AbstractAction;
 import javax.swing.InputMap;
 import javax.swing.JComponent;
 import javax.swing.JMenuItem;
 import javax.swing.KeyStroke;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
 
@@ -81,12 +85,24 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
     ((AlignFrame) getTopFrame()).getViewport().setCodingComplement(
             ((AlignFrame) getBottomFrame()).getViewport());
 
-    int width = ((AlignFrame) getTopFrame()).getWidth();
-    // about 50 pixels for the SplitFrame's title bar etc
+    /*
+     * estimate width and height of SplitFrame; this.getInsets() doesn't seem to
+     * give the full additional size (a few pixels short)
+     */
+    UIDefaults defaults = UIManager.getDefaults();
+    Set<Object> keySet = defaults.keySet();
+    for (Object key : keySet)
+    {
+      System.out.println(key.toString() + " = "
+              + UIManager.get(key).toString());
+    }
+    int widthFudge = Platform.isAMac() ? 28 : 28; // Windows tbc
+    int heightFudge = Platform.isAMac() ? 50 : 50; // tbc
+    int width = ((AlignFrame) getTopFrame()).getWidth() + widthFudge;
     int height = ((AlignFrame) getTopFrame()).getHeight()
-            + ((AlignFrame) getBottomFrame()).getHeight() + 50;
-    // about 65 pixels for Desktop decorators on Windows
-    height = Math.min(height, Desktop.instance.getHeight() - 65);
+            + ((AlignFrame) getBottomFrame()).getHeight() + DIVIDER_SIZE
+            + heightFudge;
+    height = fitHeightToDesktop(height);
     setSize(width, height);
 
     adjustLayout();
@@ -101,6 +117,27 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
   }
 
   /**
+   * Reduce the height if too large to fit in the Desktop. Also adjust the
+   * divider location in proportion.
+   * 
+   * @param height
+   *          in pixels
+   * @return original or reduced height
+   */
+  public int fitHeightToDesktop(int height)
+  {
+    // allow about 65 pixels for Desktop decorators on Windows
+
+    int newHeight = Math.min(height, Desktop.instance.getHeight() - 65);
+    if (newHeight != height)
+    {
+      int oldDividerLocation = getDividerLocation();
+      setDividerLocation(oldDividerLocation * newHeight / height);
+    }
+    return newHeight;
+  }
+
+  /**
    * Set the top and bottom frames to listen to each others Commands (e.g. Edit,
    * Order).
    */
index 347c1b2..63a8654 100644 (file)
@@ -1,7 +1,6 @@
 /*
-
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
index f316c5e..97cd777 100755 (executable)
@@ -123,7 +123,7 @@ public class FeaturesFile extends AlignFile
    *          - process html strings into plain text
    * @return true if features were added
    */
-  public boolean parse(AlignmentI align, Hashtable colours,
+  public boolean parse(AlignmentI align, Map colours,
           boolean removeHTML)
   {
     return parse(align, colours, null, removeHTML, false);
index 9fbf9ee..9ac56b5 100755 (executable)
@@ -31,6 +31,7 @@ import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
 import jalview.gui.Desktop;
 import jalview.gui.Jalview2XML;
+import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.schemes.ColourSchemeI;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.MessageManager;
@@ -375,8 +376,8 @@ public class FileLoader implements Runnable
                       .getHiddenSequences();
               boolean showSeqFeatures = ((ComplexAlignFile) source)
                       .isShowSeqFeatures();
-              ColourSchemeI cs = ((ComplexAlignFile) source)
-                      .getColourScheme();
+              String colourSchemeName = ((ComplexAlignFile) source)
+                      .getGlobalColourScheme();
               FeaturesDisplayedI fd = ((ComplexAlignFile) source)
                       .getDisplayedFeatures();
               alignFrame = new AlignFrame(al, hiddenSeqs, colSel,
@@ -385,7 +386,12 @@ public class FileLoader implements Runnable
               alignFrame.getViewport().setShowSequenceFeatures(
                       showSeqFeatures);
               alignFrame.getViewport().setFeaturesDisplayed(fd);
-              alignFrame.changeColour(cs);
+              ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+                      colourSchemeName, al);
+              if (cs != null)
+              {
+                alignFrame.changeColour(cs);
+              }
             }
             else
             {
index 0d0fae9..0cb7c00 100644 (file)
@@ -25,7 +25,6 @@ import jalview.api.ComplexAlignFile;
 import jalview.api.FeaturesDisplayedI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.ColourSchemeI;
 
 import java.io.IOException;
 import java.io.StringReader;
@@ -40,7 +39,7 @@ public class HtmlFile extends AlignFile implements ComplexAlignFile
 
   public static final String FILE_DESC = "HTML";
 
-  private ColourSchemeI colourScheme;
+  private String globalColourScheme;
 
   private boolean showSeqFeatures;
 
@@ -108,7 +107,7 @@ public class HtmlFile extends AlignFile implements ComplexAlignFile
       this.seqGroups = jsonFile.getSeqGroups();
       this.annotations = jsonFile.getAnnotations();
       this.showSeqFeatures = jsonFile.isShowSeqFeatures();
-      this.colourScheme = jsonFile.getColourScheme();
+      this.globalColourScheme = jsonFile.getGlobalColourScheme();
       this.hiddenSequences = jsonFile.getHiddenSequences();
       this.columnSelection = jsonFile.getColumnSelection();
       this.displayedFeatures = jsonFile.getDisplayedFeatures();
@@ -135,14 +134,14 @@ public class HtmlFile extends AlignFile implements ComplexAlignFile
     this.showSeqFeatures = showSeqFeatures;
   }
 
-  public ColourSchemeI getColourScheme()
+  public String getGlobalColourScheme()
   {
-    return colourScheme;
+    return globalColourScheme;
   }
 
-  public void setColourScheme(ColourSchemeI colourScheme)
+  public void setColourScheme(String globalColourScheme)
   {
-    this.colourScheme = colourScheme;
+    this.globalColourScheme = globalColourScheme;
   }
 
   public ColumnSelection getColumnSelection()
index 7cbde64..ea32985 100644 (file)
@@ -76,6 +76,10 @@ public class HtmlSvgOutput
                   .getSelectedFile().getParent());
           file = chooser.getSelectedFile();
         }
+        else
+        {
+          return;
+        }
       }
 
       AlignmentDimension aDimension = ap.getAlignmentDimension();
index a241e0e..82916f9 100755 (executable)
@@ -260,6 +260,10 @@ public class IdentifyFile
           {
             break;
           }
+          if (data == null)
+          {
+            break;
+          }
         }
 
         if (data.indexOf("{\"") > -1)
index 5160316..6fe06eb 100644 (file)
@@ -40,11 +40,10 @@ import jalview.datamodel.SequenceI;
 import jalview.json.binding.biojson.v1.AlignmentAnnotationPojo;
 import jalview.json.binding.biojson.v1.AlignmentPojo;
 import jalview.json.binding.biojson.v1.AnnotationPojo;
-import jalview.json.binding.biojson.v1.JalviewBioJsColorSchemeMapper;
+import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.json.binding.biojson.v1.SequenceFeaturesPojo;
 import jalview.json.binding.biojson.v1.SequenceGrpPojo;
 import jalview.json.binding.biojson.v1.SequencePojo;
-import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
 
@@ -63,8 +62,6 @@ import org.json.simple.parser.JSONParser;
 
 public class JSONFile extends AlignFile implements ComplexAlignFile
 {
-  private ColourSchemeI colourScheme;
-
   private static String version = new BuildDetails().getVersion();
 
   private String webstartUrl = "http://www.jalview.org/services/launchApp";
@@ -75,7 +72,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
 
   public static final String FILE_DESC = "JSON";
 
-  private String globalColorScheme;
+  private String globalColourScheme;
 
   private boolean showSeqFeatures;
 
@@ -183,7 +180,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         jsonSeqPojo.setSeq(seq.getSequenceAsString());
         jsonAlignmentPojo.getSeqs().add(jsonSeqPojo);
       }
-      jsonAlignmentPojo.setGlobalColorScheme(globalColorScheme);
+      jsonAlignmentPojo.setGlobalColorScheme(globalColourScheme);
       jsonAlignmentPojo.getAppSettings().put("application", application);
       jsonAlignmentPojo.getAppSettings().put("version", version);
       jsonAlignmentPojo.getAppSettings().put("webStartUrl", webstartUrl);
@@ -212,6 +209,13 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         jsonAlignmentPojo
                 .setAlignAnnotation(annotationToJsonPojo(annotations));
       }
+      else
+      {
+        if (globalColourScheme.equalsIgnoreCase("RNA Helices"))
+        {
+          jsonAlignmentPojo.setGlobalColorScheme("None");
+        }
+      }
 
       if (exportSettings.isExportFeatures())
       {
@@ -405,11 +409,10 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
 
       if (jvSettingsJsonObj != null)
       {
-        String jsColourScheme = (String) jvSettingsJsonObj
+        globalColourScheme = (String) jvSettingsJsonObj
                 .get("globalColorScheme");
         Boolean showFeatures = Boolean.valueOf(jvSettingsJsonObj.get(
                 "showSeqFeatures").toString());
-        setColourScheme(getJalviewColorScheme(jsColourScheme));
         setShowSeqFeatures(showFeatures);
         parseHiddenSeqRefsAsList(jvSettingsJsonObj);
         parseHiddenCols(jvSettingsJsonObj);
@@ -435,6 +438,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         seqs.add(seq);
         seqMap.put(seqUniqueId, seq);
       }
+
+
       parseFeatures(jsonSeqArray);
 
       for (Iterator<JSONObject> seqGrpIter = seqGrpJsonArray.iterator(); seqGrpIter
@@ -472,10 +477,11 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
             }
           }
         }
-        ColourSchemeI grpColourScheme = getJalviewColorScheme(colourScheme);
-        SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName,
-                grpColourScheme, displayBoxes, displayText, colourText,
+        SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, null,
+                displayBoxes, displayText, colourText,
                 startRes, endRes);
+        seqGrp.cs = ColourSchemeMapper.getJalviewColourScheme(colourScheme,
+                seqGrp);
         seqGrp.setShowNonconserved(showNonconserved);
         seqGrp.setDescription(description);
         this.seqGroups.add(seqGrp);
@@ -520,7 +526,6 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
                 .toString(), annotations);
         this.annotations.add(alignAnnot);
       }
-
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -600,42 +605,14 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
     }
   }
 
-  public static ColourSchemeI getJalviewColorScheme(
-          String bioJsColourSchemeName)
-  {
-    ColourSchemeI jalviewColor = null;
-    for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper
-            .values())
-    {
-      if (cs.getBioJsName().equalsIgnoreCase(bioJsColourSchemeName)
-              || cs.getJalviewName()
-                      .equalsIgnoreCase(bioJsColourSchemeName))
-      {
-        jalviewColor = cs.getJvColourScheme();
-        break;
-      }
-    }
-    return jalviewColor;
-  }
-
-  public String getGlobalColorScheme()
-  {
-    return globalColorScheme;
-  }
-
-  public void setGlobalColorScheme(String globalColorScheme)
-  {
-    this.globalColorScheme = globalColorScheme;
-  }
-
-  public ColourSchemeI getColourScheme()
+  public String getGlobalColourScheme()
   {
-    return colourScheme;
+    return globalColourScheme;
   }
 
-  public void setColourScheme(ColourSchemeI colourScheme)
+  public void setGlobalColorScheme(String globalColourScheme)
   {
-    this.colourScheme = colourScheme;
+    this.globalColourScheme = globalColourScheme;
   }
 
   @Override
@@ -671,7 +648,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
         annotations.add(annot);
       }
     }
-    globalColorScheme = ColourSchemeProperty.getColourName(viewport
+    globalColourScheme = ColourSchemeProperty.getColourName(viewport
             .getGlobalColourScheme());
     setDisplayedFeatures(viewport.getFeaturesDisplayed());
     showSeqFeatures = viewport.isShowSequenceFeatures();
index 64095d0..a105999 100644 (file)
@@ -170,6 +170,40 @@ public abstract class GPDBSearchPanel extends JPanel
         validateSelection();
       }
     });
+    tbl_summary.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        validateSelection();
+        switch (evt.getKeyCode())
+        {
+        case KeyEvent.VK_ESCAPE: // escape key
+          btn_back_ActionPerformed();
+          break;
+        case KeyEvent.VK_ENTER: // enter key
+          if (btn_ok.isEnabled())
+          {
+            btn_ok_ActionPerformed();
+          }
+          evt.consume();
+          break;
+        case KeyEvent.VK_TAB: // tab key
+          if (evt.isShiftDown())
+          {
+            tabbedPane.requestFocus();
+          }
+          else
+          {
+            btn_back.requestFocus();
+          }
+          evt.consume();
+          break;
+        default:
+          return;
+        }
+      }
+    });
 
     btn_back.setFont(new java.awt.Font("Verdana", 0, 12));
     btn_back.setText(MessageManager.getString("action.back"));
@@ -180,6 +214,17 @@ public abstract class GPDBSearchPanel extends JPanel
         btn_back_ActionPerformed();
       }
     });
+    btn_back.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        if (evt.getKeyCode() == KeyEvent.VK_ENTER)
+        {
+          btn_back_ActionPerformed();
+        }
+      }
+    });
 
     btn_ok.setEnabled(false);
     btn_ok.setFont(new java.awt.Font("Verdana", 0, 12));
@@ -191,6 +236,18 @@ public abstract class GPDBSearchPanel extends JPanel
         btn_ok_ActionPerformed();
       }
     });
+    btn_ok.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        if (evt.getKeyCode() == KeyEvent.VK_ENTER)
+        {
+          btn_ok_ActionPerformed();
+        }
+      }
+    });
+
     btn_cancel.setFont(new java.awt.Font("Verdana", 0, 12));
     btn_cancel.setText(MessageManager.getString("action.cancel"));
     btn_cancel.addActionListener(new java.awt.event.ActionListener()
@@ -200,6 +257,17 @@ public abstract class GPDBSearchPanel extends JPanel
         btn_cancel_ActionPerformed();
       }
     });
+    btn_cancel.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        if (evt.getKeyCode() == KeyEvent.VK_ENTER)
+        {
+          btn_cancel_ActionPerformed();
+        }
+      }
+    });
 
     scrl_searchResult.setPreferredSize(new Dimension(500, 300));
     scrl_searchResult
index 39b47ff..f06d8f0 100644 (file)
@@ -33,6 +33,8 @@ import javax.swing.plaf.basic.BasicInternalFrameUI;
 
 public class GSplitFrame extends JInternalFrame
 {
+  protected static final int DIVIDER_SIZE = 5;
+
   private static final long serialVersionUID = 1L;
 
   private GAlignFrame topFrame;
@@ -41,6 +43,12 @@ public class GSplitFrame extends JInternalFrame
 
   private JSplitPane splitPane;
 
+  /*
+   * proportional position of split divider; saving this allows it to be
+   * restored after hiding one half and resizing
+   */
+  private double dividerRatio;
+
   /**
    * Constructor
    * 
@@ -65,12 +73,23 @@ public class GSplitFrame extends JInternalFrame
     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topFrame,
             bottomFrame);
     splitPane.setVisible(true);
-    final double ratio = bottomFrame.getHeight() == 0 ? 0.5d : topFrame
-            .getHeight()
-            / (double) (topFrame.getHeight() + bottomFrame.getHeight());
-    splitPane.setDividerLocation(ratio);
-    splitPane.setResizeWeight(ratio);
-    splitPane.setDividerSize(5);
+
+    /*
+     * set divider split at 50:50, or restore saved split if loading from
+     * project
+     */
+    int topFrameHeight = topFrame.getHeight();
+    splitPane.setDividerSize(DIVIDER_SIZE);
+    if (topFrameHeight == 0)
+    {
+      setRelativeDividerLocation(0.5d); // as a proportion
+    }
+    else
+    {
+      int dividerPosition = topFrameHeight + DIVIDER_SIZE / 2;
+      splitPane.setDividerLocation(dividerPosition); // absolute position
+    }
+    splitPane.setResizeWeight(0.5d);
     add(splitPane);
   }
 
@@ -139,11 +158,25 @@ public class GSplitFrame extends JInternalFrame
   }
 
   /**
-   * Make the complement of the specified split component visible or hidden,
-   * adjusting the position of the split divide.
+   * Makes the complement of the specified split component visible or hidden,
+   * restoring or saving the position of the split divide.
    */
   public void setComplementVisible(Object alignFrame, boolean show)
   {
+    /*
+     * save divider ratio on hide, restore on show
+     */
+    if (show)
+    {
+      setRelativeDividerLocation(dividerRatio);
+    }
+    else
+    {
+      this.dividerRatio = splitPane.getDividerLocation()
+              / (double) (splitPane.getHeight() - splitPane
+                      .getDividerSize());
+    }
+
     if (alignFrame == this.topFrame)
     {
       this.bottomFrame.setVisible(show);
@@ -152,12 +185,40 @@ public class GSplitFrame extends JInternalFrame
     {
       this.topFrame.setVisible(show);
     }
-    if (show)
-    {
-      // SplitPane needs nudging to restore 50-50 split
-      // TODO save/restore other ratios
-      splitPane.setDividerLocation(0.5d);
-    }
+
     validate();
   }
+
+  /**
+   * Set the divider location as a proportion (0 <= r <= 1) of the height <br>
+   * Warning: this overloads setDividerLocation(int), and getDividerLocation()
+   * returns the int (pixel count) value
+   * 
+   * @param r
+   */
+  public void setRelativeDividerLocation(double r)
+  {
+    this.dividerRatio = r;
+    splitPane.setDividerLocation(r);
+  }
+
+  /**
+   * Sets the divider location (in pixels from top)
+   * 
+   * @return
+   */
+  protected void setDividerLocation(int p)
+  {
+    splitPane.setDividerLocation(p);
+  }
+
+  /**
+   * Returns the divider location (in pixels from top)
+   * 
+   * @return
+   */
+  protected int getDividerLocation()
+  {
+    return splitPane.getDividerLocation();
+  }
 }
index c4043c4..25924f0 100644 (file)
@@ -37,6 +37,8 @@ import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.Arrays;
@@ -162,7 +164,7 @@ public abstract class GStructureChooser extends JPanel implements
         toolTipText = getValueAt(rowIndex, colIndex).toString();
       } catch (Exception e)
       {
-        e.printStackTrace();
+        // e.printStackTrace();
       }
       toolTipText = (toolTipText == null ? null
               : (toolTipText.length() > 500 ? JvSwingUtils.wrapTooltip(
@@ -209,21 +211,104 @@ public abstract class GStructureChooser extends JPanel implements
   {
     tbl_summary.setAutoCreateRowSorter(true);
     tbl_summary.getTableHeader().setReorderingAllowed(false);
+    tbl_summary.addMouseListener(new MouseAdapter()
+    {
+      public void mouseClicked(MouseEvent e)
+      {
+        validateSelections();
+      }
+
+      public void mouseReleased(MouseEvent e)
+      {
+        validateSelections();
+      }
+    });
+    tbl_summary.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        validateSelections();
+        switch (evt.getKeyCode())
+        {
+        case KeyEvent.VK_ESCAPE: // escape key
+          mainFrame.dispose();
+          break;
+        case KeyEvent.VK_ENTER: // enter key
+          if (btn_view.isEnabled())
+          {
+            ok_ActionPerformed();
+          }
+          break;
+        case KeyEvent.VK_TAB: // tab key
+          if (evt.isShiftDown())
+          {
+            pnl_filter.requestFocus();
+          }
+          else
+          {
+            btn_view.requestFocus();
+          }
+          evt.consume();
+          break;
+        default:
+          return;
+        }
+      }
+    });
     tbl_local_pdb.setAutoCreateRowSorter(true);
     tbl_local_pdb.getTableHeader().setReorderingAllowed(false);
     tbl_local_pdb.addMouseListener(new MouseAdapter()
     {
       public void mouseClicked(MouseEvent e)
       {
-        updateCurrentView();
+        validateSelections();
       }
 
       public void mouseReleased(MouseEvent e)
       {
-        updateCurrentView();
+        validateSelections();
+      }
+    });
+    tbl_local_pdb.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        validateSelections();
+        switch (evt.getKeyCode())
+        {
+        case KeyEvent.VK_ESCAPE: // escape key
+          mainFrame.dispose();
+          break;
+        case KeyEvent.VK_ENTER: // enter key
+          if (btn_view.isEnabled())
+          {
+            ok_ActionPerformed();
+          }
+          break;
+        case KeyEvent.VK_TAB: // tab key
+          if (evt.isShiftDown())
+          {
+            cmb_filterOption.requestFocus();
+          }
+          else
+          {
+            if (btn_view.isEnabled())
+            {
+            btn_view.requestFocus();
+            }
+            else
+            {
+              btn_cancel.requestFocus();
+            }
+          }
+          evt.consume();
+        default:
+          return;
+        }
       }
     });
-
     btn_view.setFont(new java.awt.Font("Verdana", 0, 12));
     btn_view.setText(MessageManager.getString("action.view"));
     btn_view.addActionListener(new java.awt.event.ActionListener()
@@ -233,6 +318,18 @@ public abstract class GStructureChooser extends JPanel implements
         ok_ActionPerformed();
       }
     });
+    btn_view.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        if (evt.getKeyCode() == KeyEvent.VK_ENTER)
+        {
+          ok_ActionPerformed();
+        }
+      }
+    });
+
     btn_cancel.setFont(new java.awt.Font("Verdana", 0, 12));
     btn_cancel.setText(MessageManager.getString("action.cancel"));
     btn_cancel.addActionListener(new java.awt.event.ActionListener()
@@ -242,6 +339,17 @@ public abstract class GStructureChooser extends JPanel implements
         mainFrame.dispose();
       }
     });
+    btn_cancel.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        if (evt.getKeyCode() == KeyEvent.VK_ENTER)
+        {
+          mainFrame.dispose();
+        }
+      }
+    });
 
     btn_pdbFromFile.setFont(new java.awt.Font("Verdana", 0, 12));
     String btn_title = MessageManager.getString("label.select_pdb_file");
@@ -253,6 +361,17 @@ public abstract class GStructureChooser extends JPanel implements
         pdbFromFile_actionPerformed();
       }
     });
+    btn_pdbFromFile.addKeyListener(new KeyAdapter()
+    {
+      @Override
+      public void keyPressed(KeyEvent evt)
+      {
+        if (evt.getKeyCode() == KeyEvent.VK_ENTER)
+        {
+          pdbFromFile_actionPerformed();
+        }
+      }
+    });
 
     scrl_foundStructures.setPreferredSize(new Dimension(500, 300));
     scrl_foundStructures
diff --git a/src/jalview/json/binding/biojson/v1/ColourSchemeMapper.java b/src/jalview/json/binding/biojson/v1/ColourSchemeMapper.java
new file mode 100644 (file)
index 0000000..aeab34c
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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.json.binding.biojson.v1;
+
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.schemes.Blosum62ColourScheme;
+import jalview.schemes.BuriedColourScheme;
+import jalview.schemes.ClustalxColourScheme;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.HelixColourScheme;
+import jalview.schemes.HydrophobicColourScheme;
+import jalview.schemes.NucleotideColourScheme;
+import jalview.schemes.PIDColourScheme;
+import jalview.schemes.PurinePyrimidineColourScheme;
+import jalview.schemes.RNAHelicesColour;
+import jalview.schemes.RNAInteractionColourScheme;
+import jalview.schemes.StrandColourScheme;
+import jalview.schemes.TCoffeeColourScheme;
+import jalview.schemes.TaylorColourScheme;
+import jalview.schemes.TurnColourScheme;
+import jalview.schemes.ZappoColourScheme;
+
+public class ColourSchemeMapper
+{
+  private static ColourSchemeI csZappo, csTaylor, csNucleotide, csPurine,
+          csHelix, csTurn, csStrand, csBuried, csHydro,
+          csRNAInteractionType, csPID, csBlosum62 = null;
+  static
+  {
+    csZappo = new ZappoColourScheme();
+    csTaylor = new TaylorColourScheme();
+    csNucleotide = new NucleotideColourScheme();
+    csPurine = new PurinePyrimidineColourScheme();
+    csHelix = new HelixColourScheme();
+    csTurn = new TurnColourScheme();
+    csStrand = new StrandColourScheme();
+    csBuried = new BuriedColourScheme();
+    csHydro = new HydrophobicColourScheme();
+    csRNAInteractionType = new RNAInteractionColourScheme();
+    csPID = new PIDColourScheme();
+    csBlosum62 = new Blosum62ColourScheme();
+  }
+  public static ColourSchemeI getJalviewColourScheme(
+          String colourSchemeName, AnnotatedCollectionI annotCol)
+  {
+    switch (colourSchemeName.toUpperCase())
+    {
+    case "ZAPPO":
+      return csZappo;
+    case "TAYLOR":
+      return csTaylor;
+    case "NUCLEOTIDE":
+      return csNucleotide;
+    case "PURINE":
+    case "PURINE/PYRIMIDINE":
+      return csPurine;
+    case "HELIX":
+    case "HELIX PROPENSITY":
+      return csHelix;
+    case "TURN":
+    case "TURN PROPENSITY":
+      return csTurn;
+    case "STRAND":
+    case "STRAND PROPENSITY":
+      return csStrand;
+    case "BURIED":
+    case "BURIED INDEX":
+      return csBuried;
+    case "HYDRO":
+    case "HYDROPHOBIC":
+      return csHydro;
+    case "RNA INTERACTION TYPE":
+      return csRNAInteractionType;
+    case "PID":
+    case "% IDENTITY":
+      return csPID;
+    case "BLOSUM62":
+      return csBlosum62;
+    case "T-COFFEE SCORES":
+      return (annotCol != null) ? new TCoffeeColourScheme(annotCol) : null;
+    case "RNA HELICES":
+      return (annotCol != null) ? new RNAHelicesColour(annotCol) : null;
+    case "CLUSTAL":
+      return (annotCol != null) ? new ClustalxColourScheme(annotCol, null)
+              : null;
+    case "USER DEFINED":
+      return null;
+    default:
+      return null;
+    }
+  }
+}
diff --git a/src/jalview/json/binding/biojson/v1/JalviewBioJsColorSchemeMapper.java b/src/jalview/json/binding/biojson/v1/JalviewBioJsColorSchemeMapper.java
deleted file mode 100644 (file)
index 4d9f8ec..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9)
- * Copyright (C) 2015 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.json.binding.biojson.v1;
-
-import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.NucleotideColourScheme;
-import jalview.schemes.PIDColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.RNAInteractionColourScheme;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.ZappoColourScheme;
-
-public enum JalviewBioJsColorSchemeMapper
-{
-
-  USER_DEFINED("User Defined", "user defined", null), NONE("None", "foo",
-          null), CLUSTAL("Clustal", "clustal", null), ZAPPO("Zappo",
-          "zappo", new ZappoColourScheme()), TAYLOR("Taylor", "taylor",
-          new TaylorColourScheme()), NUCLEOTIDE("Nucleotide", "nucleotide",
-          new NucleotideColourScheme()), PURINE_PYRIMIDINE(
-          "Purine/Pyrimidine", "purine", new PurinePyrimidineColourScheme()), HELIX_PROPENSITY(
-          "Helix Propensity", "helix", new HelixColourScheme()), TURN_PROPENSITY(
-          "Turn Propensity", "turn", new TurnColourScheme()), STRAND_PROPENSITY(
-          "Strand Propensity", "strand", new StrandColourScheme()), BURIED_INDEX(
-          "Buried Index", "buried", new BuriedColourScheme()), HYDROPHOBIC(
-          "Hydrophobic", "hydro", new HydrophobicColourScheme()),
-
-  // The color types below are not yet supported by BioJs MSA viewer
-  T_COFFE_SCORES("T-Coffee Scores", "T-Coffee Scores", null), RNA_INT_TYPE(
-          "RNA Interaction type", "RNA Interaction type",
-          new RNAInteractionColourScheme()), BLOSUM62("Blosum62",
-          "Blosum62", new Blosum62ColourScheme()), RNA_HELICES(
-          "RNA Helices", "RNA Helices", null), PERCENTAGE_IDENTITY(
-          "% Identity", "pid", new PIDColourScheme());
-
-  private String jalviewName;
-
-  private String bioJsName;
-
-  private ColourSchemeI jvColourScheme;
-
-  private JalviewBioJsColorSchemeMapper(String jalviewName,
-          String bioJsName, ColourSchemeI jvColourScheme)
-  {
-    this.jalviewName = jalviewName;
-    this.bioJsName = bioJsName;
-    this.setJvColourScheme(jvColourScheme);
-  }
-
-  public String getJalviewName()
-  {
-    return jalviewName;
-  }
-
-  public String getBioJsName()
-  {
-    return bioJsName;
-  }
-
-  public ColourSchemeI getJvColourScheme()
-  {
-    return jvColourScheme;
-  }
-
-  public void setJvColourScheme(ColourSchemeI jvColourScheme)
-  {
-    this.jvColourScheme = jvColourScheme;
-  }
-
-}
index fef31b2..e3ff02e 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.util;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.StringTokenizer;
 import java.util.regex.Pattern;
 
@@ -52,9 +53,9 @@ public class ParseHtmlBodyAndLinks
     return htmlContent;
   }
 
-  ArrayList<String> links = new ArrayList<String>();
+  List<String> links = new ArrayList<String>();
 
-  StringBuffer sb = new StringBuffer();
+  String content;
 
   /**
    * result of parsing description - with or without HTML tags
@@ -64,7 +65,7 @@ public class ParseHtmlBodyAndLinks
   public String getContent()
   {
 
-    return sb.toString();
+    return content;
   }
 
   /**
@@ -72,12 +73,19 @@ public class ParseHtmlBodyAndLinks
    * 
    * @return
    */
-  public ArrayList<String> getLinks()
+  public List<String> getLinks()
   {
     return links;
   }
 
   /**
+   * Parses the given html and
+   * <ul>
+   * <li>extracts any 'href' links to a list of "displayName|url" strings,
+   * retrievable by #getLinks</li>
+   * <li>extracts the remaining text (with %LINK% placeholders replacing hrefs),
+   * retrievable by #getContent</li>
+   * </ul>
    * 
    * @param description
    *          - html or text content to be parsed
@@ -89,6 +97,7 @@ public class ParseHtmlBodyAndLinks
   public ParseHtmlBodyAndLinks(String description, boolean removeHTML,
           String newline)
   {
+    StringBuilder sb = new StringBuilder(description.length());
     if (description == null || description.length() == 0)
     {
       htmlContent = false;
@@ -105,7 +114,7 @@ public class ParseHtmlBodyAndLinks
     String tag = null;
     while (st.hasMoreElements())
     {
-      token = st.nextToken("&>");
+      token = st.nextToken(">");
       if (token.equalsIgnoreCase("html") || token.startsWith("/"))
       {
         continue;
@@ -135,18 +144,6 @@ public class ParseHtmlBodyAndLinks
       {
         sb.append(newline);
       }
-      else if (token.startsWith("lt;"))
-      {
-        sb.append("<" + token.substring(3));
-      }
-      else if (token.startsWith("gt;"))
-      {
-        sb.append(">" + token.substring(3));
-      }
-      else if (token.startsWith("amp;"))
-      {
-        sb.append("&" + token.substring(4));
-      }
       else
       {
         sb.append(token);
@@ -156,11 +153,18 @@ public class ParseHtmlBodyAndLinks
     {
       // instead of parsing the html into plaintext
       // clean the description ready for embedding in html
-      sb = new StringBuffer(LEFT_ANGLE_BRACKET_PATTERN.matcher(description)
-              .replaceAll("&lt;"));
-
+      sb = new StringBuilder(LEFT_ANGLE_BRACKET_PATTERN
+              .matcher(description).replaceAll("&lt;"));
     }
+    content = translateEntities(sb.toString());
+  }
 
+  private String translateEntities(String s)
+  {
+    s = s.replaceAll("&amp;", "&");
+    s = s.replaceAll("&lt;", "<");
+    s = s.replaceAll("&gt;", ">");
+    return s;
   }
 
   /**
@@ -171,7 +175,7 @@ public class ParseHtmlBodyAndLinks
    */
   public String getNonHtmlContent()
   {
-    return isHtmlContent() ? sb.toString() : orig;
+    return isHtmlContent() ? content : orig;
   }
 
 }
index fdd40e4..e361413 100644 (file)
@@ -683,7 +683,7 @@ public abstract class FeatureRendererModel implements
   @Override
   public Map<String, Object> getFeatureColours()
   {
-    return new ConcurrentHashMap<String, Object>(featureColours);
+    return featureColours;
   }
 
   /**
index bf791e2..b9ed2e7 100644 (file)
@@ -34,7 +34,9 @@ import jalview.ws.AWsJob;
 import jalview.ws.JobStateSummary;
 import jalview.ws.WSClientI;
 
+import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.Map;
 import java.util.Vector;
 
 import vamsas.objects.simple.MsaResult;
@@ -168,7 +170,7 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
      * 
      * @return null or { Alignment(+features and annotation), NewickFile)}
      */
-    public Object[] getAlignment(Alignment dataset, Hashtable featureColours)
+    public Object[] getAlignment(Alignment dataset, Map featureColours)
     {
 
       if (result != null && result.isFinished())
@@ -610,7 +612,7 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
     // NewickFile nf[] = new NewickFile[jobs.length];
     for (int j = 0; j < jobs.length; j++)
     {
-      Hashtable featureColours = new Hashtable();
+      Map featureColours = new HashMap();
       Alignment al = null;
       NewickFile nf = null;
       if (jobs[j].hasResults())
index 7826fbd..24f38d1 100644 (file)
@@ -21,6 +21,7 @@
 
 package jalview.ws.uimodel;
 
+import jalview.bin.Cache;
 import jalview.datamodel.SequenceI;
 import jalview.ws.dbsources.PDBRestClient.PDBDocField;
 
@@ -44,12 +45,14 @@ public class PDBRestRequest
 
   private boolean allowEmptySequence;
 
+  private boolean allowUnpublishedEntries = Cache.getDefault(
+          "ALLOW_UNPUBLISHED_PDB_QUERYING", false);
+
   private int responseSize;
 
   private boolean isSortAscending;
 
-  private Collection<PDBDocField> wantedFields;// = new
-                                               // Collection<PDBDocField>();
+  private Collection<PDBDocField> wantedFields;
 
   public String getFieldToSearchBy()
   {
@@ -130,7 +133,8 @@ public class PDBRestRequest
   public String getQuery()
   {
     return fieldToSearchBy + searchTerm
-            + (isAllowEmptySeq() ? "" : " AND molecule_sequence:['' TO *]");
+            + (isAllowEmptySeq() ? "" : " AND molecule_sequence:['' TO *]")
+            + (isAllowUnpublishedEntries() ? "" : " AND status:REL");
   }
 
   public String toString()
@@ -139,4 +143,14 @@ public class PDBRestRequest
             + " isAsc: " + isAscending() + " Associated Seq : "
             + associatedSequence;
   }
+
+  public boolean isAllowUnpublishedEntries()
+  {
+    return allowUnpublishedEntries;
+  }
+
+  public void setAllowUnpublishedEntries(boolean allowUnpublishedEntries)
+  {
+    this.allowUnpublishedEntries = allowUnpublishedEntries;
+  }
 }
diff --git a/test/jalview/io/FeaturesFileTest.java b/test/jalview/io/FeaturesFileTest.java
new file mode 100644 (file)
index 0000000..f56cd51
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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.io;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceFeature;
+import jalview.gui.AlignFrame;
+
+import java.awt.Color;
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+public class FeaturesFileTest
+{
+
+  static String TestFiles[][] = {
+ { "Test example features import/export",
+      "examples/uniref50.fa", "examples/exampleFeatures.txt" } };
+
+  @Test(groups = { "Functional" })
+  public void testParse() throws Exception
+  {
+    testFeaturesFileIO("Features file test");
+  }
+
+  public static AlignmentI readAlignmentFile(File f) throws IOException
+  {
+    System.out.println("Reading file: " + f);
+    String ff = f.getPath();
+    FormatAdapter rf = new FormatAdapter();
+
+    AlignmentI al = rf.readFile(ff, AppletFormatAdapter.FILE,
+            new IdentifyFile().Identify(ff, AppletFormatAdapter.FILE));
+
+    al.setDataset(null); // creates dataset sequences
+    assertNotNull("Couldn't read supplied alignment data.", al);
+    return al;
+  }
+
+  /**
+   * Helper method for testing
+   * 
+   * @param testname
+   * @param f
+   *          alignment file
+   * @param featFile
+   *          features file to load on to the alignment
+   * @throws IOException
+   */
+  public static void testFeaturesFileIO(String testname) throws IOException
+  {
+    File f = new File("examples/uniref50.fa");
+    AlignmentI al = readAlignmentFile(f);
+    AlignFrame af = new AlignFrame(al, 500, 500);
+    Map<String, Object> colours = af.getFeatureRenderer()
+            .getFeatureColours();
+    FeaturesFile featuresFile = new FeaturesFile(
+            "examples/exampleFeatures.txt", FormatAdapter.FILE);
+    assertTrue("Test " + testname + "\nFailed to parse features file.",
+            featuresFile.parse(al.getDataset(), colours, true));
+
+    /*
+     * Refetch the colour map from the FeatureRenderer (to confirm it has been
+     * updated - JAL-1904), and verify (some) feature group colours
+     */
+    colours = af.getFeatureRenderer().getFeatureColours();
+    assertEquals("26 feature group colours not found", 26, colours.size());
+    assertEquals(colours.get("Cath"), new Color(0x93b1d1));
+    assertEquals(colours.get("ASX-MOTIF"), new Color(0x6addbb));
+
+    /*
+     * verify (some) features on sequences
+     */
+    SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
+            .getSequenceFeatures(); // FER_CAPAA
+    assertEquals(7, sfs.length);
+    SequenceFeature sf = sfs[0];
+    assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
+    assertEquals(39, sf.begin);
+    assertEquals(39, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("METAL", sf.type);
+    sf = sfs[1];
+    assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
+    assertEquals(44, sf.begin);
+    assertEquals(44, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("METAL", sf.type);
+    sf = sfs[2];
+    assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
+    assertEquals(47, sf.begin);
+    assertEquals(47, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("METAL", sf.type);
+    sf = sfs[3];
+    assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
+    assertEquals(77, sf.begin);
+    assertEquals(77, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("METAL", sf.type);
+    sf = sfs[4];
+    assertEquals("Fer2 Status: True Positive Pfam 8_8%LINK%",
+            sf.description);
+    assertEquals("Pfam 8_8|http://pfam.sanger.ac.uk/family/PF00111",
+            sf.links.get(0).toString());
+    assertEquals(8, sf.begin);
+    assertEquals(83, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("Pfam", sf.type);
+    sf = sfs[5];
+    assertEquals("Ferredoxin_fold Status: True Positive ", sf.description);
+    assertEquals(3, sf.begin);
+    assertEquals(93, sf.end);
+    assertEquals("uniprot", sf.featureGroup);
+    assertEquals("Cath", sf.type);
+    sf = sfs[6];
+    assertEquals(
+            "High confidence server. Only hits with scores over 0.8 are reported. PHOSPHORYLATION (T) 89_8%LINK%",
+            sf.description);
+    assertEquals(
+            "PHOSPHORYLATION (T) 89_8|http://www.cbs.dtu.dk/cgi-bin/proview/webface-link?seqid=P83527&amp;service=NetPhos-2.0",
+            sf.links.get(0).toString());
+    assertEquals(89, sf.begin);
+    assertEquals(89, sf.end);
+    assertEquals("netphos", sf.featureGroup);
+    assertEquals("PHOSPHORYLATION (T)", sf.type);
+  }
+}
index 9bdc2b5..e0b050f 100644 (file)
@@ -33,8 +33,8 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
+import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.schemes.ColourSchemeI;
-import jalview.schemes.ZappoColourScheme;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -124,9 +124,11 @@ public class JSONFileTest
     grpSeqs.add(seqs[2]);
     grpSeqs.add(seqs[3]);
     grpSeqs.add(seqs[4]);
-    ColourSchemeI scheme = JSONFile.getJalviewColorScheme("zappo");
     SequenceGroup seqGrp = new SequenceGroup(grpSeqs, "JGroup:1883305585",
-            scheme, true, true, false, 21, 29);
+            null, true, true, false, 21, 29);
+    ColourSchemeI scheme = ColourSchemeMapper.getJalviewColourScheme(
+            "zappo", seqGrp);
+    seqGrp.cs = scheme;
     seqGrp.setShowNonconserved(false);
     seqGrp.setDescription(null);
 
@@ -232,7 +234,10 @@ public class JSONFileTest
               jf.getColumnSelection(), AlignFrame.DEFAULT_WIDTH,
               AlignFrame.DEFAULT_HEIGHT);
       af.getViewport().setShowSequenceFeatures(jf.isShowSeqFeatures());
-      af.changeColour(jf.getColourScheme());
+      String colourSchemeName = jf.getGlobalColourScheme();
+      ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+              colourSchemeName, alignment);
+      af.changeColour(cs);
       af.getViewport().setFeaturesDisplayed(jf.getDisplayedFeatures());
 
       formatAdapter = new AppletFormatAdapter(af.alignPanel, exportSettings);
@@ -315,11 +320,13 @@ public class JSONFileTest
   @Test(groups = { "Functional" })
   public void colorSchemeTest()
   {
-    Assert.assertNotNull(testJsonFile.getColourScheme(),
+    Assert.assertNotNull(testJsonFile.getGlobalColourScheme(),
             "Colourscheme is null, parsing failed!");
-    Assert.assertTrue(
-            testJsonFile.getColourScheme() instanceof ZappoColourScheme,
+    Assert.assertEquals(testJsonFile.getGlobalColourScheme(), "Zappo",
             "Zappo colour scheme expected!");
+    // Assert.assertTrue(
+    // testJsonFile.getGlobalColourScheme() instanceof ZappoColourScheme,
+    // "Zappo colour scheme expected!");
   }
 
   @Test(groups = { "Functional" })
@@ -419,13 +426,14 @@ public class JSONFileTest
             + actualGrp.getStartRes());
     System.out.println(expectedGrp.getEndRes() + " | "
             + actualGrp.getEndRes());
+    System.out.println(expectedGrp.cs + " | " + actualGrp.cs);
 
     if (expectedGrp.getName().equals(actualGrp.getName())
             && expectedGrp.getColourText() == actualGrp.getColourText()
             && expectedGrp.getDisplayBoxes() == actualGrp.getDisplayBoxes()
             && expectedGrp.getIgnoreGapsConsensus() == actualGrp
                     .getIgnoreGapsConsensus()
-            && expectedGrp.cs.equals(actualGrp.cs)
+            && (expectedGrp.cs.getClass().equals(actualGrp.cs.getClass()))
             && expectedGrp.getSequences().size() == actualGrp
                     .getSequences().size()
             && expectedGrp.getStartRes() == actualGrp.getStartRes()
diff --git a/test/jalview/util/ParseHtmlBodyAndLinksTest.java b/test/jalview/util/ParseHtmlBodyAndLinksTest.java
new file mode 100644 (file)
index 0000000..5e8cd8c
--- /dev/null
@@ -0,0 +1,74 @@
+package jalview.util;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import org.testng.annotations.Test;
+
+public class ParseHtmlBodyAndLinksTest
+{
+  @Test(groups = { "Functional" })
+  public void testParseHtml_noLinks()
+  {
+    ParseHtmlBodyAndLinks testee = new ParseHtmlBodyAndLinks(
+            "<html>something here</html>", false, "\n");
+    assertEquals("something here", testee.getContent());
+    assertEquals("something here", testee.getNonHtmlContent());
+
+    // second argument makes no difference??
+    testee = new ParseHtmlBodyAndLinks("<html>something here</html>", true,
+            "\n");
+    assertEquals("something here", testee.getContent());
+    assertEquals("something here", testee.getNonHtmlContent());
+  }
+
+  @Test(groups = { "Functional" })
+  public void testParseHtml_withLinks()
+  {
+    ParseHtmlBodyAndLinks testee = new ParseHtmlBodyAndLinks(
+            "<html>Please click <a href=\"http://www.nowhere.com\">on this</a> to learn more about <a href=\"http://www.somewhere.com/here\">this</a></html>",
+            false, "\n");
+    assertEquals(
+            "Please click on this%LINK% to learn more about this%LINK%",
+            testee.getContent());
+    assertEquals(
+            "Please click on this%LINK% to learn more about this%LINK%",
+            testee.getNonHtmlContent());
+    assertEquals(2, testee.getLinks().size());
+    assertEquals("on this|http://www.nowhere.com", testee.getLinks().get(0));
+    assertEquals("this|http://www.somewhere.com/here", testee.getLinks()
+            .get(1));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testParseHtml_withLinksWithParameters()
+  {
+    ParseHtmlBodyAndLinks testee = new ParseHtmlBodyAndLinks(
+            "<html>Please click <a href=\"http://www.nowhere.com?id=234&taxon=human\">on this</a> to learn more</html>",
+            false, "\n");
+    assertEquals("Please click on this%LINK% to learn more",
+            testee.getContent());
+    assertEquals("Please click on this%LINK% to learn more",
+            testee.getNonHtmlContent());
+    assertEquals(1, testee.getLinks().size());
+    assertEquals("on this|http://www.nowhere.com?id=234&taxon=human",
+            testee.getLinks().get(0));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testParseHtml_withLinksWithEncoding()
+  {
+    ParseHtmlBodyAndLinks testee = new ParseHtmlBodyAndLinks(
+            "<html>Please click <a href=\"http://www.nowhere.com?id=234&amp;taxon=human&amp;id&gt;3&amp;id&lt;10\">on this</a> to learn &amp;&lt;&gt;more</html>",
+            false, "\n");
+    // html encoding in the text body is translated
+    assertEquals("Please click on this%LINK% to learn &<>more",
+            testee.getContent());
+    assertEquals("Please click on this%LINK% to learn &<>more",
+            testee.getNonHtmlContent());
+    assertEquals(1, testee.getLinks().size());
+    // html encoding in the url links is not translated
+    assertEquals(
+            "on this|http://www.nowhere.com?id=234&amp;taxon=human&amp;id&gt;3&amp;id&lt;10",
+            testee.getLinks().get(0));
+  }
+}
index 6688dba..23e849c 100644 (file)
@@ -264,7 +264,7 @@ public class PDBRestClientTest
           if (pdbJsonDoc.get(field.getCode()) == null)
           {
             // System.out.println(">>>\t" + field.getCode());
-            assertTrue(field.getClass()
+            assertTrue(field.getCode()
                     + " has been removed from PDB doc Entity",
                     !pdbJsonResponseString.contains(field.getCode()));
           }