Merge remote-tracking branch 'origin/bug/JAL-2282' into develop
authorkiramt <k.mourao@dundee.ac.uk>
Wed, 16 Nov 2016 15:55:37 +0000 (15:55 +0000)
committerkiramt <k.mourao@dundee.ac.uk>
Wed, 16 Nov 2016 15:55:37 +0000 (15:55 +0000)
47 files changed:
THIRDPARTYLIBS
examples/javascript/facebox-1.3.js [new file with mode: 0644]
help/html/colourSchemes/abovePID.html
help/html/features/featuresFormat.html
help/html/features/search.html
resources/lang/Messages_es.properties
src/MCview/PDBChain.java
src/jalview/analysis/AlignSeq.java
src/jalview/appletgui/AppletJmol.java
src/jalview/appletgui/AppletJmolBinding.java
src/jalview/appletgui/ExtJmol.java
src/jalview/bin/Jalview.java
src/jalview/datamodel/PDBEntry.java
src/jalview/datamodel/SequenceFeature.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AppJmol.java
src/jalview/gui/AppJmolBinding.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/Desktop.java
src/jalview/gui/JalviewChimeraBindingModel.java
src/jalview/gui/StructureViewerBase.java
src/jalview/io/BioJsHTMLOutput.java
src/jalview/io/HTMLOutput.java
src/jalview/io/HtmlSvgOutput.java
src/jalview/jbgui/GSequenceLink.java
src/jalview/schemes/ResidueProperties.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/structures/models/AAStructureBindingModel.java
src/jalview/util/Comparison.java
src/jalview/util/Platform.java
src/jalview/ws/sifts/SiftsClient.java
test/jalview/bin/CommandLineOperations.java
test/jalview/datamodel/SequenceFeatureTest.java
test/jalview/ext/htsjdk/TestHtsContigDb.java
test/jalview/gui/AlignFrameTest.java
test/jalview/gui/AppVarnaTest.java
test/jalview/io/BioJsHTMLOutputTest.java
test/jalview/io/PfamFormatInputTest.java
test/jalview/schemes/ResiduePropertiesTest.java
test/jalview/structures/models/AAStructureBindingModelTest.java
test/jalview/util/ComparisonTest.java
test/jalview/util/PlatformTest.java [new file with mode: 0644]
test/jalview/ws/jabaws/DisorderAnnotExportImport.java
test/jalview/ws/sifts/SiftsClientTest.java

index 31ad2f5..7d12783 100644 (file)
@@ -58,4 +58,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/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 614764b..ad47dae 100755 (executable)
@@ -36,9 +36,10 @@ td {
   </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
-    percentage of the time. For instance selecting the threshold to be
-    100 will only colour those columns with 100 % identity. This
-    threshold option can be applied to the Zappo, Taylor, Hydrophobicity
-    and User colour schemes.</p>
+    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>
+   <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>
 </body>
 </html>
index ec1e093..fd6b99f 100755 (executable)
     a colour the feature).</p>
 
   <p>
-    If your sequence annotation is already available in GFF Format (see
-    <a href="http://gmod.org/wiki/GFF2">gmod.org/wiki/GFF2</a>), then
-    you can leave it as is, after first adding a line containing only
+    If your sequence annotation is already available in <a href="http://gmod.org/wiki/GFF2">GFF2</a> (http://gmod.org/wiki/GFF2) or
+    <a href="https://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md">GFF3</a> 
+    (http://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md) format, 
+    then you can leave it as is, after first adding a line containing only
     'GFF' after any Jalview feature colour definitions (<em>this
-      mixed format capability was added in Jalview 2.6</em>). Alternately,
+    mixed format capability was added in Jalview 2.6</em>). Alternately,
     you can use Jalview's own sequence feature annotation format, which
     additionally allows HTML and URLs to be directly attached to each
     piece of annotation.
index 9766782..796d623 100755 (executable)
@@ -73,7 +73,7 @@ td {
     the match. For example, a simple query like &quot;ACDED&quot; would
     match all occurences of that string, but &quot;ACD+ED&quot; matches
     both 'ACDDED' and 'ACDDDDDDDDED'. More usefully, the query
-    &quot;[ILGVMA]{;5,}&quot; would find stretches of small, hydrophobic
+    &quot;[GVATC]{;5,}&quot; would find stretches of small, hydrophobic
     amino acids of at least five residues in length.</p>
   <p>
     The table below describes some of the regular expression syntax:<br>
index 50bfd24..96c8ef2 100644 (file)
@@ -351,8 +351,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
index 7774dac..783a4e2 100755 (executable)
@@ -31,6 +31,7 @@ import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.StructureImportSettings;
 import jalview.structure.StructureMapping;
+import jalview.util.Comparison;
 
 import java.awt.Color;
 import java.util.List;
@@ -146,7 +147,9 @@ public class PDBChain
         pdbpos++;
       }
 
-      if (as.astr1.charAt(i) == as.astr2.charAt(i))
+      boolean sameResidue = Comparison.isSameResidue(as.astr1.charAt(i),
+              as.astr2.charAt(i), false);
+      if (sameResidue)
       {
         if (pdbpos >= residues.size())
         {
index 3ad3188..86bf721 100755 (executable)
@@ -620,7 +620,10 @@ public class AlignSeq
       {
         if ((i + (j * len)) < astr1.length())
         {
-          if (astr1.charAt(i + (j * len)) == astr2.charAt(i + (j * len))
+          boolean sameChar = Comparison.isSameResidue(
+                  astr1.charAt(i + (j * len)), astr2.charAt(i + (j * len)),
+                  false);
+          if (sameChar
                   && !jalview.util.Comparison.isGap(astr1.charAt(i
                           + (j * len))))
           {
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..3a36ed5 100644 (file)
@@ -45,9 +45,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 +113,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 +145,7 @@ class AppletJmolBinding extends JalviewJmolBinding
     // do nothing.
   }
 
+  @Override
   public void selectionChanged(BS arg0)
   {
     // TODO Auto-generated method stub
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 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 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 c75d6f2..0baa78e 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;
     }
index fbac400..56287a9 100644 (file)
@@ -74,7 +74,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 +99,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 +1083,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 +1143,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 +1195,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 +1243,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);
index 7ba9186..4a9bf5f 100644 (file)
@@ -40,6 +40,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;
@@ -63,6 +64,9 @@ 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
    */
@@ -191,10 +195,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 ext.edu.ucsf.rbvi.strucviz2.StructureManager(true));
   }
@@ -244,11 +247,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;
     }
 
@@ -257,7 +263,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);
   }
@@ -758,18 +764,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()]);
@@ -1067,28 +1061,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    * 
    * @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
@@ -1125,4 +1097,31 @@ 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..1372749 100644 (file)
@@ -1341,14 +1341,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)
index 4db029c..9f1162f 100644 (file)
@@ -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);
     }
   }
 
@@ -981,16 +981,28 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @throws PrinterException
    *           DOCUMENT ME!
    */
-  public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)
+  public int printUnwrapped(int pwidth, int pheight, int pi,
+          Graphics... pg)
           throws PrinterException
   {
+    boolean isMultiGraphics = pg.length > 1;
+    int G0 = 0; // Graphic index of idPanel graphics in multi-graphics mode or
+                // entire graphics for non mulit-graphics mode
+    int G1 = 0; // Graphic index of alignmentPanel graphics for multi-graphics
+                // mode
+    if (isMultiGraphics)
+    {
+      G0 = 0;
+      G1 = 1;
+    }
+
     int idWidth = getVisibleIdWidth(false);
     FontMetrics fm = getFontMetrics(av.getFont());
     int scaleHeight = av.getCharHeight() + fm.getDescent();
 
-    pg.setColor(Color.white);
-    pg.fillRect(0, 0, pwidth, pheight);
-    pg.setFont(av.getFont());
+    pg[G0].setColor(Color.white);
+    pg[G0].fillRect(0, 0, pwidth, pheight);
+    pg[G0].setFont(av.getFont());
 
     // //////////////////////////////////
     // / How many sequences and residues can we fit on a printable page?
@@ -1047,17 +1059,31 @@ public class AlignmentPanel extends GAlignmentPanel implements
     }
 
     // draw Scale
-    pg.translate(idWidth, 0);
-    getScalePanel().drawScale(pg, startRes, endRes, pwidth - idWidth,
-            scaleHeight);
-    pg.translate(-idWidth, scaleHeight);
+    if (isMultiGraphics)
+    {
+      pg[G1].translate(0, 0);
+      getScalePanel().drawScale(pg[G1], startRes, endRes,
+              pwidth - idWidth, scaleHeight);
+      pg[G1].translate(-idWidth, scaleHeight);
+    }
+    else
+    {
+      pg[G0].translate(idWidth, 0);
+      getScalePanel().drawScale(pg[G0], startRes, endRes, pwidth - idWidth,
+              scaleHeight);
+      pg[G0].translate(-idWidth, scaleHeight);
+    }
 
     // //////////////
     // Draw the ids
     Color currentColor = null;
     Color currentTextColor = null;
 
-    pg.setFont(getIdPanel().getIdCanvas().getIdfont());
+    if (isMultiGraphics)
+    {
+      pg[G0].translate(0, scaleHeight);
+    }
+    pg[G0].setFont(getIdPanel().getIdCanvas().getIdfont());
 
     SequenceI seq;
     for (int i = startSeq; i < endSeq; i++)
@@ -1075,45 +1101,70 @@ public class AlignmentPanel extends GAlignmentPanel implements
         currentTextColor = Color.black;
       }
 
-      pg.setColor(currentColor);
-      pg.fillRect(0, (i - startSeq) * av.getCharHeight(), idWidth,
+      pg[G0].setColor(currentColor);
+      pg[G0].fillRect(0, (i - startSeq) * av.getCharHeight(), idWidth,
               av.getCharHeight());
 
-      pg.setColor(currentTextColor);
+      pg[G0].setColor(currentTextColor);
 
       int xPos = 0;
       if (av.isRightAlignIds())
       {
-        fm = pg.getFontMetrics();
+        fm = pg[G0].getFontMetrics();
         xPos = idWidth
                 - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
                 - 4;
       }
 
-      pg.drawString(seq.getDisplayId(av.getShowJVSuffix()), xPos,
+      pg[G0].drawString(seq.getDisplayId(av.getShowJVSuffix()), xPos,
               (((i - startSeq) * av.getCharHeight()) + av.getCharHeight())
                       - (av.getCharHeight() / 5));
     }
 
-    pg.setFont(av.getFont());
+    pg[G0].setFont(av.getFont());
+
 
     // draw main sequence panel
-    pg.translate(idWidth, 0);
-    getSeqPanel().seqCanvas.drawPanel(pg, startRes, endRes, startSeq,
-            endSeq, 0);
+    pg[G0].translate(idWidth, 0);
+    if (isMultiGraphics)
+    {
+      pg[G1].translate(idWidth, 0);
+      getSeqPanel().seqCanvas.drawPanel(pg[G1], startRes, endRes,
+              startSeq, endSeq, 0);
+    }
+    else
+    {
+      getSeqPanel().seqCanvas.drawPanel(pg[G0], startRes, endRes, startSeq,
+              endSeq, 0);
+    }
 
     if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight()))
     {
-      // draw annotation - need to offset for current scroll position
+      // draw annotation label - 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);
-      getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
-              pg, -1, startRes, endRes + 1);
-      pg.translate(0, -offset);
+      pg[G0].translate(0, offset);
+      pg[G0].translate(-idWidth - 3,
+              (endSeq - startSeq) * av.getCharHeight() + 3);
+      getAlabels().drawComponent(pg[G0], idWidth);
+      pg[G0].translate(idWidth + 3, 0);
+      pg[G0].translate(0, -offset);
+      if (isMultiGraphics)
+      {
+        // draw annotation - need to offset for current scroll position
+        pg[G1].translate(0, offset);
+        pg[G1].translate(-idWidth - 3,
+                (endSeq - startSeq) * av.getCharHeight() + 3);
+        pg[G1].translate(idWidth + 3, 0);
+        getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(),
+                av, pg[G1], -1, startRes, endRes + 1);
+        pg[G1].translate(0, -offset);
+      }
+      else
+      {
+        getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(),
+                av, pg[G0], -1, startRes, endRes + 1);
+        pg[G0].translate(0, -offset);
+      }
     }
 
     return Printable.PAGE_EXISTS;
@@ -1136,8 +1187,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;
@@ -1316,8 +1367,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
         {
           if (im.getGraphics() != null)
           {
-            printWrappedAlignment(im.getGraphics(), aDimension.getWidth(),
-                    aDimension.getHeight() + boarderBottomOffset, 0);
+            printWrappedAlignment(aDimension.getWidth(),
+                    aDimension.getHeight() + boarderBottomOffset, 0,
+                    im.getGraphics());
             im.writeImage();
           }
         }
@@ -1325,8 +1377,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
         {
           if (im.getGraphics() != null)
           {
-            printUnwrapped(im.getGraphics(), aDimension.getWidth(),
-                    aDimension.getHeight(), 0);
+            printUnwrapped(aDimension.getWidth(), aDimension.getHeight(),
+                    0, im.getGraphics());
             im.writeImage();
           }
         }
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 1c54a5e..546890e 100644 (file)
@@ -41,10 +41,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;
   }
 
@@ -113,6 +112,7 @@ public class AppJmolBinding extends JalviewJmolBinding
     // appJmolWindow.repaint();
     javax.swing.SwingUtilities.invokeLater(new Runnable()
     {
+      @Override
       public void run()
       {
         appJmolWindow.updateTitleAndMenus();
@@ -121,6 +121,7 @@ public class AppJmolBinding extends JalviewJmolBinding
     });
   }
 
+  @Override
   public void updateColours(Object source)
   {
     AlignmentPanel ap = (AlignmentPanel) source;
@@ -144,6 +145,7 @@ public class AppJmolBinding extends JalviewJmolBinding
     // msWalltime);
   }
 
+  @Override
   public void showUrl(String url)
   {
     showUrl(url, "jmol");
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 d06dd26..28606f1 100644 (file)
@@ -2282,12 +2282,19 @@ public class Desktop extends jalview.jbgui.GDesktop implements
           // only need to check links if there is one with a
           // SEQUENCE_ID which is not the default EMBL_EBI link
           ListIterator<String> li = links.listIterator();
-          Boolean check = false;
-          while (li.hasNext() && !check)
+          boolean check = false;
+          List<JLabel> urls = new ArrayList<JLabel>();
+          while (li.hasNext())
           {
             String link = li.next();
-            check = (link.contains(SEQUENCE_ID) && !link
-                    .equals(EMBLEBI_STRING));
+            if (link.contains(SEQUENCE_ID) && !link.equals(EMBLEBI_STRING))
+            {
+              check = true;
+              int barPos = link.indexOf("|");
+              String urlMsg = barPos == -1 ? link : link.substring(0,
+                      barPos) + ": " + link.substring(barPos + 1);
+              urls.add(new JLabel(urlMsg));
+            }
           }
           if (!check)
           {
@@ -2306,6 +2313,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
                   MessageManager
                           .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
           msgPanel.add(msg);
+          for (JLabel url : urls)
+          {
+            msgPanel.add(url);
+          }
           msgPanel.add(msg2);
 
           final JCheckBox jcb = new JCheckBox(
@@ -2315,15 +2326,10 @@ public class Desktop extends jalview.jbgui.GDesktop implements
             @Override
             public void actionPerformed(ActionEvent e)
             {
-              // update Cache settings if checkbox is selected
-              if (jcb.isSelected())
-              {
-                Cache.setProperty("CHECKURLLINKS", "false");
-              }
-              else
-              {
-                Cache.setProperty("CHECKURLLINKS", "true");
-              }
+              // update Cache settings for "don't show this again"
+              boolean showWarningAgain = !jcb.isSelected();
+              Cache.setProperty("CHECKURLLINKS",
+                      Boolean.valueOf(showWarningAgain).toString());
             }
           });
           msgPanel.add(jcb);
index 7a54732..78ab68d 100644 (file)
@@ -32,11 +32,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;
   }
 
@@ -72,6 +73,7 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
   {
     javax.swing.SwingUtilities.invokeLater(new Runnable()
     {
+      @Override
       public void run()
       {
         cvf.updateTitleAndMenus();
@@ -80,6 +82,7 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
     });
   }
 
+  @Override
   public void updateColours(Object source)
   {
     AlignmentPanel ap = (AlignmentPanel) source;
@@ -113,6 +116,7 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
    * Send an asynchronous command to Chimera, in a new thread, optionally with
    * an 'in progress' message in a progress bar somewhere
    */
+  @Override
   protected void sendAsynchronousCommand(final String command,
           final String progressMsg)
   {
@@ -135,4 +139,6 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
     thread.start();
 
   }
+
+
 }
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..1be97f5 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,91 +57,38 @@ 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;
-        }
+      generatedFile = new File(outputFile);
 
-        @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 bioJSON = getBioJSONData();
+      String bioJSTemplateString = HTMLOutput.readFileAsString(getCurrentBJSTemplateFile());
       String generatedBioJsWithJalviewAlignmentAsJson = bioJSTemplateString
               .replaceAll("#sequenceData#", bioJSON).toString();
 
       PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
-              outputFile));
+              generatedFile));
       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);
-      }
+      exportCompleted();
+      setProgressMessage(MessageManager.formatMessage(
+              "status.export_complete", "BioJS"));
+
     } catch (NoFileSelectedException ex)
     {
       // do noting if no file was selected
@@ -162,94 +99,15 @@ public class BioJsHTMLOutput
       new OOMWarning("Creating Image for " + outputFile, err);
     } catch (Exception e)
     {
-      if (pIndicator != null && !headless)
-      {
-      pIndicator.setProgressBar(MessageManager.formatMessage(
-              "info.error_creating_file", "HTML"), pSessionId);
-      }
+      setProgressMessage(MessageManager.formatMessage(
+              "info.error_creating_file", "HTML"));
       e.printStackTrace();
     }
   }
 
-  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 +155,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 +276,22 @@ public class BioJsHTMLOutput
     BioJsHTMLOutput.bioJsMSAVersions = bioJsMSAVersions;
   }
 
+  @Override
+  public boolean isEmbedData()
+  {
+    return true;
+  }
+
+  @Override
+  public boolean isLaunchInBrowserAfterExport()
+  {
+    return true;
+  }
+
+  @Override
+  public File getExportedFile()
+  {
+    return generatedFile;
+  }
+
 }
index df0dc06..a422a38 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
 {
-  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)
-  {
-    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;
-
-    for (i = 10; i < (alignment.getWidth() - 10); i += 10)
+  public String getBioJSONData()
+  {
+    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++)
+    AlignExportSettingI exportSettings = new AlignExportSettingI()
     {
-      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++)
+      @Override
+      public boolean isExportHiddenSequences()
       {
-        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>");
-        }
+        return true;
       }
 
-      out.println("</tr>");
-    }
-
-    // ////////////
-    out.println("</table>");
-    out.println("</td></tr></table>");
-  }
-
-  void drawWrappedAlignment(PrintWriter out)
-  {
-    // //////////////////////////////////
-    // / 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())
-    {
-      int endRes = startRes + av.getWrappedWidth();
-
-      if (endRes > al.getWidth())
+      @Override
+      public boolean isExportHiddenColumns()
       {
-        endRes = al.getWidth();
+        return true;
       }
 
-      if (av.getScaleAboveWrapped())
+      @Override
+      public boolean isExportAnnotations()
       {
-        out.println("<tr>");
-
-        if (av.getScaleLeftWrapped())
-        {
-          out.println("<td colspan=\"7\">&nbsp;</td>");
-        }
-        else
-        {
-          out.println("<td colspan=\"6\">&nbsp;</td>");
-        }
-
-        for (int i = startRes + 10; i < endRes; i += 10)
-        {
-          out.println("<td colspan=\"9\">" + i + "<br>|</td><td></td>");
-        }
-
-        out.println("</tr>");
+        return true;
       }
 
-      int startPos, endPos;
-      for (int s = 0; s < al.getHeight(); s++)
+      @Override
+      public boolean isExportFeatures()
       {
-        out.println("<tr>");
-        seq = al.getSequenceAt(s);
-
-        startPos = seq.findPosition(startRes);
-        endPos = seq.findPosition(endRes) - 1;
+        return true;
+      }
 
-        String id = seq.getDisplayId(av.getShowJVSuffix());
+      @Override
+      public boolean isExportGroups()
+      {
+        return true;
+      }
 
-        out.println("<td nowrap>" + id + "&nbsp;&nbsp;</td>");
+      @Override
+      public boolean isCancelled()
+      {
+        return false;
+      }
 
-        if (av.getScaleLeftWrapped())
-        {
-          if (startPos > seq.getEnd() || endPos == 0)
-          {
-            out.println("<td nowrap>&nbsp;</td>");
-          }
-          else
-          {
-            out.println("<td nowrap>" + startPos + "&nbsp;&nbsp;</td>");
-          }
-        }
+    };
+    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;
+  }
 
-        for (int res = startRes; res < endRes; res++)
+  /**
+   * 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
+  {
+    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)
+    {
+      try
+      {
+        isReader = new InputStreamReader(url.openStream());
+        buffReader = new BufferedReader(isReader);
+        String line;
+        String lineSeparator = System.getProperty("line.separator");
+        while ((line = buffReader.readLine()) != null)
         {
-          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>");
-          }
-
+          sb.append(line).append(lineSeparator);
         }
-
-        if (av.getScaleRightWrapped()
-                && endRes < startRes + av.getWrappedWidth())
+  
+      } catch (Exception ex)
+      {
+        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 +246,125 @@ 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_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;
+  }
+
+  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..e60824a 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.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;
+  private File generatedFile;
 
-  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 file)
   {
-    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)
       {
-        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;
-        }
+        file = getOutputFile();
       }
+      generatedFile = new File(file);
     } 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
@@ -116,9 +74,11 @@ public class HtmlSvgOutput
           setProgressMessage(MessageManager.formatMessage(
                   "status.exporting_alignment_as_x_file", "HTML"));
           AlignmentDimension aDimension = ap.getAlignmentDimension();
-          SVGGraphics2D g1 = new SVGGraphics2D(aDimension.getWidth(),
+          SVGGraphics2D idPanelGraphics = new SVGGraphics2D(
+                  aDimension.getWidth(),
                   aDimension.getHeight());
-          SVGGraphics2D g2 = new SVGGraphics2D(aDimension.getWidth(),
+          SVGGraphics2D alignPanelGraphics = new SVGGraphics2D(
+                  aDimension.getWidth(),
                   aDimension.getHeight());
 
           String renderStyle = jalview.bin.Cache.getDefault(
@@ -127,8 +87,7 @@ public class HtmlSvgOutput
           // 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")))
+                  && !isHeadless())
           {
             HTMLOptions svgOption = new HTMLOptions();
             renderStyle = svgOption.getValue();
@@ -143,100 +102,44 @@ public class HtmlSvgOutput
 
           if (renderStyle.equalsIgnoreCase("Lineart"))
           {
-            g1.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+            idPanelGraphics.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
                     SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
-            g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+            alignPanelGraphics.setRenderingHint(
+                    SVGHints.KEY_DRAW_STRING_TYPE,
                     SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
           }
-          if (av.getWrapAlignment())
+          if (ap.av.getWrapAlignment())
           {
             printWrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
-                    g1, g2);
+                    alignPanelGraphics);
           }
           else
           {
           printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
-                  g1, g2);
+ idPanelGraphics, alignPanelGraphics);
           }
 
-          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);
+          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();
-          if (!(System.getProperty("java.awt.headless") != null && System
-                  .getProperty("java.awt.headless").equals("true")))
-          {
-            jalview.util.BrowserLauncher.openURL("file:///" + fileX);
-          }
+          exportCompleted();
         } catch (OutOfMemoryError err)
         {
           System.out.println("########################\n"
-                  + "OUT OF MEMORY " + fileX + "\n"
+                  + "OUT OF MEMORY " + generatedFile + "\n"
                   + "########################");
-          new OOMWarning("Creating Image for " + fileX, err);
+          new OOMWarning("Creating Image for " + generatedFile, err);
         } catch (Exception e)
         {
           e.printStackTrace();
-          pIndicator.setProgressBar(MessageManager.formatMessage(
-                  "info.error_creating_file", "HTML"), pSessionId);
+          setProgressMessage(MessageManager.formatMessage(
+                  "info.error_creating_file", "HTML"));
         }
         setProgressMessage(MessageManager.formatMessage(
                 "status.export_complete", "HTML"));
@@ -245,17 +148,6 @@ public class HtmlSvgOutput
 
   }
 
-  private void setProgressMessage(String message)
-  {
-    if (pIndicator != null && !headless)
-    {
-      pIndicator.setProgressBar(message, pSessionId);
-    }
-    else
-    {
-      System.out.println(message);
-    }
-  }
 
   static JalviewFileChooser getHTMLChooser()
   {
@@ -269,138 +161,13 @@ public class HtmlSvgOutput
   public int printUnwrapped(int pwidth, int pheight, int pi, Graphics... pg)
           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, pg);
   }
 
   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,
@@ -506,266 +273,37 @@ public class HtmlSvgOutput
     // 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");
-
-      htmlSvg.append("  function skipOverlay() {\n");
-      htmlSvg.append("    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null\n");
-      htmlSvg.append("  }\n");
-
-      htmlSvg.append("  function showOverlay() {\n");
-      htmlSvg.append("    if (skipOverlay()) return\n");
-
-      htmlSvg.append("    if ($('#facebox_overlay').length == 0)\n");
-      htmlSvg.append("      $(\"body\").append('<div id=\"facebox_overlay\" class=\"facebox_hide\"></div>')\n");
-
-      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");
-
-      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");
-
-      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");
-
-      htmlSvg.append("})(jQuery);\n");
-
+      File faceBoxJsFile = new File("examples/javascript/facebox-1.3.js");
+      try
+      {
+        htmlSvg.append(HTMLOutput.readFileAsString(faceBoxJsFile));
+      } catch (IOException e)
+      {
+        e.printStackTrace();
+      }
     }
 
     htmlSvg.append("</script>\n");
     htmlSvg.append("</html>");
     return htmlSvg.toString();
   }
+
+  @Override
+  public boolean isEmbedData()
+  {
+    return Boolean.valueOf(jalview.bin.Cache.getDefault(
+            "EXPORT_EMBBED_BIOJSON", "true"));
+  }
+
+  @Override
+  public boolean isLaunchInBrowserAfterExport()
+  {
+    return true;
+  }
+
+  @Override
+  public File getExportedFile()
+  {
+    return generatedFile;
+  }
 }
index b27752e..2689946 100755 (executable)
@@ -67,7 +67,7 @@ public class GSequenceLink extends Panel
       }
     });
     urlTB.setFont(JvSwingUtils.getLabelFont());
-    urlTB.setText("http://www.");
+    urlTB.setText("http://");
     urlTB.setBounds(new Rectangle(78, 40, 309, 23));
     urlTB.addKeyListener(new KeyAdapter()
     {
index f855fde..4d46279 100755 (executable)
@@ -935,7 +935,7 @@ public class ResidueProperties
     hydrophobic.put("D", ZERO);
     hydrophobic.put("N", ZERO);
     hydrophobic.put("S", ZERO);
-    hydrophobic.put("T", ZERO);
+    hydrophobic.put("T", ONE);
     hydrophobic.put("P", ZERO);
   }
 
index 7e691be..cad2303 100644 (file)
@@ -391,7 +391,7 @@ public class StructureSelectionManager
         registerPDBFile(pdb.getId().trim(), pdbFile);
       }
       // if PDBId is unavailable then skip SIFTS mapping execution path
-      isMapUsingSIFTs = pdb.isPPDBIdAvailable();
+      isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
 
     } catch (Exception ex)
     {
index b00f1bc..5dc3465 100644 (file)
@@ -135,19 +135,14 @@ public abstract class AAStructureBindingModel extends
    * @param protocol
    */
   public AAStructureBindingModel(StructureSelectionManager ssm,
-          PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
+          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()
@@ -674,4 +669,12 @@ public abstract class AAStructureBindingModel extends
   {
     this.finishedInit = fi;
   }
+
+  /**
+   * Returns a list of chains mapped in this viewer.
+   * 
+   * @return
+   */
+  public abstract List<String> getChainNames();
+
 }
index 0beb45b..1326647 100644 (file)
@@ -415,4 +415,29 @@ public class Comparison
             .size()]);
     return isNucleotide(oneDArray);
   }
+
+  /**
+   * Compares two residues either case sensitively or case insensitively
+   * depending on the caseSensitive flag
+   * 
+   * @param c1
+   *          first char
+   * @param c2
+   *          second char to compare with
+   * @param caseSensitive
+   *          if true comparison will be case sensitive otherwise its not
+   * @return
+   */
+  public static boolean isSameResidue(char c1, char c2,
+          boolean caseSensitive)
+  {
+    if (caseSensitive)
+    {
+      return (c1 == c2);
+    }
+    else
+    {
+      return Character.toUpperCase(c1) == Character.toUpperCase(c2);
+    }
+  }
 }
index 3fb384f..49dc7ff 100644 (file)
@@ -30,6 +30,10 @@ import java.awt.event.MouseEvent;
  */
 public class Platform
 {
+  private static Boolean isAMac = null;
+
+  private static Boolean isHeadless = null;
+
   /**
    * sorry folks - Macs really are different
    * 
@@ -37,15 +41,21 @@ public class Platform
    */
   public static boolean isAMac()
   {
-    return java.lang.System.getProperty("os.name").indexOf("Mac") > -1;
+    if (isAMac == null)
+    {
+      isAMac = System.getProperty("os.name").indexOf("Mac") > -1;
+    }
+    return isAMac.booleanValue();
 
   }
 
   public static boolean isHeadless()
   {
-    String hdls = java.lang.System.getProperty("java.awt.headless");
-
-    return hdls != null && hdls.equals("true");
+    if (isHeadless == null)
+    {
+      isHeadless = "true".equals(System.getProperty("java.awt.headless"));
+    }
+    return isHeadless;
   }
 
   /**
@@ -89,8 +99,28 @@ public class Platform
    */
   public static boolean isControlDown(MouseEvent e)
   {
-    if (isAMac())
+    boolean aMac = isAMac();
+    return isControlDown(e, aMac);
+  }
+
+  /**
+   * Overloaded version of method (to allow unit testing)
+   * 
+   * @param e
+   * @param aMac
+   * @return
+   */
+  protected static boolean isControlDown(MouseEvent e, boolean aMac)
+  {
+    if (aMac)
     {
+      /*
+       * answer false for right mouse button
+       */
+      if (e.isPopupTrigger())
+      {
+        return false;
+      }
       return (Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() & e
               .getModifiers()) != 0;
       // could we use e.isMetaDown() here?
index 83af0e0..27db604 100644 (file)
@@ -29,6 +29,7 @@ import jalview.datamodel.SequenceI;
 import jalview.io.StructureFile;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.StructureMapping;
+import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
 import jalview.util.Format;
 import jalview.xml.binding.sifts.Entry;
@@ -510,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());
 
@@ -1004,8 +1005,10 @@ public class SiftsClient implements SiftsClientI
         {
           if ((i + (j * len)) < seqRes.length())
           {
-            if (seqRes.charAt(i + (j * len)) == strRes
-                    .charAt(i + (j * len))
+            boolean sameChar = Comparison.isSameResidue(
+                    seqRes.charAt(i + (j * len)),
+                    strRes.charAt(i + (j * len)), false);
+            if (sameChar
                     && !jalview.util.Comparison.isGap(seqRes.charAt(i
                             + (j * len))))
             {
index b85536e..c79a043 100644 (file)
@@ -34,6 +34,15 @@ import org.testng.annotations.Test;
 
 public class CommandLineOperations
 {
+  private static final int TEST_TIMEOUT = 4500; // Note longer timeout needed on
+                                                // full test run than on
+                                                // individual tests
+
+  private static final int SETUP_TIMEOUT = 9000;
+
+  private static final int MINFILESIZE_SMALL = 2096;
+
+  private static final int MINFILESIZE_BIG = 4096;
 
   private ArrayList<String> successfulCMDs = new ArrayList<String>();
 
@@ -60,6 +69,7 @@ public class CommandLineOperations
       this.process = process;
     }
 
+    @Override
     public void run()
     {
       try
@@ -142,7 +152,7 @@ public class CommandLineOperations
     String cmds = "nodisplay -open examples/uniref50.fa -sortbytree -props FILE -colour zappo "
             + "-jabaws http://www.compbio.dundee.ac.uk/jabaws -nosortbytree -dasserver nickname=www.test.com "
             + "-features examples/testdata/plantfdx.features -annotations examples/testdata/plantfdx.annotations -tree examples/testdata/uniref50_test_tree";
-    Worker worker = jalviewDesktopRunner(true, cmds, 9000);
+    Worker worker = jalviewDesktopRunner(true, cmds, SETUP_TIMEOUT);
     String ln = null;
     while ((ln = worker.getOutputReader().readLine()) != null)
     {
@@ -155,7 +165,7 @@ public class CommandLineOperations
   public void setUpForCommandLineInputOperations() throws IOException
   {
     String cmds = "-open examples/uniref50.fa -noquestionnaire -nousagestats";
-    Worker worker = jalviewDesktopRunner(false, cmds, 9000);
+    Worker worker = jalviewDesktopRunner(false, cmds, SETUP_TIMEOUT);
     String ln = null;
     int count = 0;
     while ((ln = worker.getErrorReader().readLine()) != null)
@@ -204,7 +214,8 @@ public class CommandLineOperations
       worker.process.destroy();
       Assert.fail("Jalview did not exit after "
               + type
-              + " generation (try running test again to verify - timeout at 9000ms). ["
+              + " generation (try running test again to verify - timeout at "
+              + SETUP_TIMEOUT + "ms). ["
               + harg + "]");
     }
     new File(fileName).delete();
@@ -252,36 +263,36 @@ public class CommandLineOperations
   {
     return new Object[][] {
         { "nodisplay -open examples/uniref50.fa", " -eps",
-            "test_uniref50_out.eps", true, 4096, 4000 },
+            "test_uniref50_out.eps", true, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "nodisplay -open examples/uniref50.fa", " -eps",
-            "test_uniref50_out.eps", false, 4096, 4000 },
+            "test_uniref50_out.eps", false, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "nogui -open examples/uniref50.fa", " -eps",
-            "test_uniref50_out.eps", true, 4096, 4000 },
+            "test_uniref50_out.eps", true, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "nogui -open examples/uniref50.fa", " -eps",
-            "test_uniref50_out.eps", false, 4096, 4000 },
+            "test_uniref50_out.eps", false, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -eps",
-            "test_uniref50_out.eps", true, 4096, 4000 },
+            "test_uniref50_out.eps", true, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -svg",
-            "test_uniref50_out.svg", false, 4096, 3000 },
+            "test_uniref50_out.svg", false, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -png",
-            "test_uniref50_out.png", true, 4096, 3000 },
+            "test_uniref50_out.png", true, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -html",
-            "test_uniref50_out.html", true, 4096, 3000 },
+            "test_uniref50_out.html", true, MINFILESIZE_BIG, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -fasta",
-            "test_uniref50_out.mfa", true, 2096, 3000 },
+            "test_uniref50_out.mfa", true, MINFILESIZE_SMALL, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -clustal",
-            "test_uniref50_out.aln", true, 2096, 3000 },
+            "test_uniref50_out.aln", true, MINFILESIZE_SMALL, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -msf",
-            "test_uniref50_out.msf", true, 2096, 3000 },
+            "test_uniref50_out.msf", true, MINFILESIZE_SMALL, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -pileup",
-            "test_uniref50_out.aln", true, 2096, 3000 },
+            "test_uniref50_out.aln", true, MINFILESIZE_SMALL, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -pir",
-            "test_uniref50_out.pir", true, 2096, 3000 },
+            "test_uniref50_out.pir", true, MINFILESIZE_SMALL, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -pfam",
-            "test_uniref50_out.pfam", true, 2096, 3000 },
+            "test_uniref50_out.pfam", true, MINFILESIZE_SMALL, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -blc",
-            "test_uniref50_out.blc", true, 2096, 3000 },
+            "test_uniref50_out.blc", true, MINFILESIZE_SMALL, TEST_TIMEOUT },
         { "headless -open examples/uniref50.fa", " -jalview",
-            "test_uniref50_out.jvp", true, 2096, 3000 }, };
+            "test_uniref50_out.jvp", true, MINFILESIZE_SMALL, TEST_TIMEOUT }, };
   }
 }
index 2ec824d..5150337 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());
index f8c53b0..bdc14db 100644 (file)
@@ -33,7 +33,7 @@ import org.testng.annotations.Test;
  */
 public class TestHtsContigDb
 {
-  @Test
+  @Test(groups = "Functional")
   public final void testHTSReferenceSequence() throws Exception
   {
     HtsContigDb remmadb = new HtsContigDb("REEMADB", new File(
index 316d9af..b2ef3f7 100644 (file)
@@ -37,7 +37,7 @@ import org.testng.annotations.Test;
 public class AlignFrameTest
 {
 
-  @Test
+  @Test(groups = "Functional")
   public void testHideFeatureColumns()
   {
     SequenceI seq1 = new Sequence("Seq1", "ABCDEFGHIJ");
index 5bc0ddf..92770d5 100644 (file)
@@ -28,7 +28,7 @@ import org.testng.annotations.Test;
 
 public class AppVarnaTest
 {
-  @Test
+  @Test(groups = "Functional")
   public void testReplaceOddGaps()
   {
     String struct = "{(<]}>)";
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 0eaf94b..fb99865 100644 (file)
@@ -29,20 +29,20 @@ import org.testng.annotations.Test;
 
 public class PfamFormatInputTest
 {
-  @Test
+  @Test(groups = "Functional")
   public void testPfamFormatNoLimits() throws IOException
   {
-    AlignmentI al = new jalview.io.AppletFormatAdapter().readFile("ASEQ"
+    AlignmentI al = new AppletFormatAdapter().readFile("ASEQ"
             + '\t' + "...--FFAFAFF--", AppletFormatAdapter.PASTE, "PFAM");
     Assert.assertEquals(1, al.getHeight(), "Wrong number of sequences");
     Assert.assertTrue(al.hasValidSequence(),
             "Didn't extract limits from PFAM ID");
   }
 
-  @Test
+  @Test(groups = "Functional")
   public void testPfamFormatValidLimits() throws IOException
   {
-    AlignmentI al = new jalview.io.AppletFormatAdapter().readFile(
+    AlignmentI al = new AppletFormatAdapter().readFile(
             "ASEQ/15-25" + '\t' + "...--FFAFAFF--",
             AppletFormatAdapter.PASTE, "PFAM");
     Assert.assertEquals(1, al.getHeight(), "Wrong number of sequences");
index 41d7448..be6a10c 100644 (file)
@@ -1570,7 +1570,7 @@ public class ResiduePropertiesTest
     checkProperty("polar", "YWHRKTSNDEQ-*X");
     checkProperty("positive", "HKR-*");
     checkProperty("proline", "P-*");
-    checkProperty("hydrophobic", "MILVFYWHKCGAC-*X");
+    checkProperty("hydrophobic", "MILVFYWHKTGAC-*X");
   }
 
   /**
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 9aab66c..b71c270 100644 (file)
@@ -188,4 +188,16 @@ public class ComparisonTest
     assertTrue(Comparison.isNucleotideSequence("a A-g.GcCtTuU", true));
     assertFalse(Comparison.isNucleotideSequence("a A-g.GcCtTuU", false));
   }
+
+  @Test(groups = { "Functional" })
+  public void testIsSameResidue()
+  {
+    assertTrue(Comparison.isSameResidue('a', 'a', false));
+    assertTrue(Comparison.isSameResidue('a', 'a', true));
+    assertTrue(Comparison.isSameResidue('A', 'a', false));
+    assertTrue(Comparison.isSameResidue('a', 'A', false));
+
+    assertFalse(Comparison.isSameResidue('a', 'A', true));
+    assertFalse(Comparison.isSameResidue('A', 'a', true));
+  }
 }
diff --git a/test/jalview/util/PlatformTest.java b/test/jalview/util/PlatformTest.java
new file mode 100644 (file)
index 0000000..88fd1b9
--- /dev/null
@@ -0,0 +1,80 @@
+package jalview.util;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.awt.Button;
+import java.awt.Event;
+import java.awt.event.MouseEvent;
+
+import org.testng.annotations.Test;
+
+public class PlatformTest
+{
+  Button b = new Button();
+
+  /**
+   * isControlDown for Mac should answer true for Meta-down, but not for right
+   * mouse (popup trigger)
+   */
+  @Test(groups = "Functional")
+  public void testIsControlDown_mac()
+  {
+    int clickCount = 1;
+    boolean isPopupTrigger = false;
+    int buttonNo = MouseEvent.BUTTON1;
+    boolean mac = true;
+
+    int mods = 0;
+    // not concerned with MouseEvent id, when, x, y, xAbs, yAbs values
+    assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+
+    mods = Event.CTRL_MASK;
+    assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+
+    mods = Event.META_MASK;
+    assertTrue(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+
+    isPopupTrigger = true;
+    assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+
+    isPopupTrigger = false;
+    buttonNo = MouseEvent.BUTTON2;
+    mods = 0;
+    assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+  }
+
+  /**
+   * If not a Mac, we only care whether CTRL_MASK modifier is set on the mouse
+   * event
+   */
+  @Test(groups = "Functional")
+  public void testIsControlDown_notMac()
+  {
+    int clickCount = 1;
+    boolean isPopupTrigger = false;
+    int buttonNo = MouseEvent.BUTTON1;
+    boolean mac = false;
+
+    int mods = 0;
+    // not concerned with MouseEvent id, when, x, y, xAbs, yAbs values
+    assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+
+    mods = Event.CTRL_MASK;
+    assertTrue(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+
+    mods = Event.CTRL_MASK | Event.SHIFT_MASK | Event.ALT_MASK;
+    clickCount = 2;
+    buttonNo = 2;
+    isPopupTrigger = true;
+    assertTrue(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
+            0, 0, clickCount, isPopupTrigger, buttonNo), mac));
+  }
+}
index 9f62481..2067659 100644 (file)
@@ -119,11 +119,11 @@ public class DisorderAnnotExportImport
     {
       orig_alig.deleteAnnotation(aa);
     }
-    testAnnotationFileIO("Testing IUPred Annotation IO", orig_alig);
+    checkAnnotationFileIO("Testing IUPred Annotation IO", orig_alig);
 
   }
 
-  public static void testAnnotationFileIO(String testname, AlignmentI al)
+  static void checkAnnotationFileIO(String testname, AlignmentI al)
   {
     try
     {
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"