Merge branch 'develop' into releases/Release_2_11_Branch
authorJim Procter <jprocter@issues.jalview.org>
Thu, 13 Jun 2019 15:02:05 +0000 (16:02 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Thu, 13 Jun 2019 15:02:05 +0000 (16:02 +0100)
105 files changed:
.gitignore
build.gradle
doc/building-OLD.html [deleted file]
doc/building.md [new file with mode: 0644]
doc/convert.sh [new file with mode: 0644]
doc/github.css [new file with mode: 0644]
getdown/lib/getdown-core-1.8.3-SNAPSHOT.jar
getdown/lib/getdown-launcher.jar
getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/Application.java
getdown/src/getdown/core/src/main/java/jalview/bin/MemorySetting.java [new file with mode: 0644]
getdown/src/getdown/launcher/src/main/java/com/threerings/getdown/launcher/Getdown.java
getdown/src/getdown/mvn_cmd
gradle.properties
help/help/html/releases.html
j11lib/getdown-core.jar
j8lib/getdown-core.jar
resources/lang/Messages.properties
resources/lang/Messages_es.properties
schemas/jalview.xsd
schemas/vamsas.xsd
src/jalview/analysis/AlignmentUtils.java
src/jalview/bin/Jalview.java
src/jalview/bin/JalviewTaskbar.java
src/jalview/bin/Launcher.java
src/jalview/bin/MemorySetting.java [new file with mode: 0644]
src/jalview/datamodel/DBRefEntry.java
src/jalview/datamodel/GeneLociI.java
src/jalview/datamodel/GeneLocus.java [new file with mode: 0644]
src/jalview/datamodel/Sequence.java
src/jalview/ext/ensembl/EnsemblFeatures.java
src/jalview/ext/ensembl/EnsemblGene.java
src/jalview/ext/ensembl/EnsemblLookup.java
src/jalview/ext/ensembl/EnsemblMap.java
src/jalview/ext/htsjdk/VCFReader.java
src/jalview/gui/APQHandlers.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/CrossRefAction.java
src/jalview/gui/Desktop.java
src/jalview/gui/FeatureTypeSettings.java
src/jalview/gui/JvSwingUtils.java
src/jalview/gui/Preferences.java
src/jalview/gui/SplitFrame.java
src/jalview/io/BackupFilenameParts.java
src/jalview/io/BackupFiles.java
src/jalview/io/BackupFilesPresetEntry.java [new file with mode: 0644]
src/jalview/io/IntKeyStringValueEntry.java [new file with mode: 0644]
src/jalview/io/SequenceAnnotationReport.java
src/jalview/io/gff/SequenceOntologyLite.java
src/jalview/io/vcf/VCFLoader.java
src/jalview/jbgui/GDesktop.java
src/jalview/jbgui/GPreferences.java
src/jalview/project/Jalview2XML.java
src/jalview/util/Platform.java
src/jalview/util/ShortcutKeyMaskExWrapper.java
src/jalview/util/ShortcutKeyMaskExWrapper11.java [new file with mode: 0644]
src/jalview/util/ShortcutKeyMaskExWrapper8.java [new file with mode: 0644]
src/jalview/util/ShortcutKeyMaskExWrapperI.java [new file with mode: 0644]
src/jalview/xml/binding/jalview/AlcodonFrame.java
src/jalview/xml/binding/jalview/Annotation.java
src/jalview/xml/binding/jalview/AnnotationColourScheme.java
src/jalview/xml/binding/jalview/AnnotationElement.java
src/jalview/xml/binding/jalview/DoubleMatrix.java
src/jalview/xml/binding/jalview/DoubleVector.java
src/jalview/xml/binding/jalview/Feature.java
src/jalview/xml/binding/jalview/FeatureMatcher.java
src/jalview/xml/binding/jalview/FeatureMatcherSet.java
src/jalview/xml/binding/jalview/FilterBy.java
src/jalview/xml/binding/jalview/JalviewModel.java
src/jalview/xml/binding/jalview/JalviewUserColours.java
src/jalview/xml/binding/jalview/MapListType.java
src/jalview/xml/binding/jalview/Mapping.java
src/jalview/xml/binding/jalview/NoValueColour.java
src/jalview/xml/binding/jalview/ObjectFactory.java
src/jalview/xml/binding/jalview/PcaDataType.java
src/jalview/xml/binding/jalview/Pdbentry.java
src/jalview/xml/binding/jalview/Sequence.java
src/jalview/xml/binding/jalview/SequenceSet.java
src/jalview/xml/binding/jalview/SequenceType.java
src/jalview/xml/binding/jalview/ThresholdType.java
src/jalview/xml/binding/jalview/VAMSAS.java
src/jalview/xml/binding/jalview/WebServiceParameterSet.java
src/jalview/xml/binding/jalview/package-info.java
test/jalview/analysis/AlignmentUtilsTests.java
test/jalview/gui/SeqPanelTest.java
test/jalview/io/BackupFilesTest.java
test/jalview/io/backupfilestest.fa [moved from examples/backupfilestest.fa with 100% similarity]
test/jalview/io/testProps.jvprops
test/jalview/project/Jalview2xmlTests.java
utils/HelpLinksChecker.java
utils/install4j/DS_Store
utils/install4j/DS_Store_1 [new file with mode: 0644]
utils/install4j/DS_Store_2 [new file with mode: 0644]
utils/install4j/DS_Store_3 [new file with mode: 0644]
utils/install4j/Uninstall Old Jalview.app/Contents/Info.plist [new file with mode: 0644]
utils/install4j/Uninstall Old Jalview.app/Contents/MacOS/applet [new file with mode: 0755]
utils/install4j/Uninstall Old Jalview.app/Contents/PkgInfo [new file with mode: 0644]
utils/install4j/Uninstall Old Jalview.app/Contents/Resources/Scripts/main.scpt [new file with mode: 0644]
utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.icns [new file with mode: 0644]
utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.rsrc [new file with mode: 0644]
utils/install4j/Uninstall Old Jalview.app/Contents/Resources/description.rtfd/TXT.rtf [new file with mode: 0644]
utils/install4j/Uninstall Old Jalview.scpt [new file with mode: 0644]
utils/install4j/install4j_template.install4j
utils/install4j/uninstall_app_dmg_file_inclusions.sh [new file with mode: 0644]
utils/install4j/uninstall_old_jalview.icns [new file with mode: 0644]
utils/install4j/uninstall_old_jalview_files.xml [new file with mode: 0644]

index a2a64e7..0b21681 100644 (file)
@@ -29,3 +29,4 @@ TESTNG
 /utils/install4j/jalview-installers-*.install4j
 *.swp
 /bin
+/doc/building.html
index 07a4095..3876753 100644 (file)
@@ -1,6 +1,10 @@
 import org.apache.tools.ant.filters.ReplaceTokens
 //import org.apache.tools.ant.filters.ReplaceRegexp
 import org.gradle.internal.os.OperatingSystem
+import org.gradle.plugins.ide.eclipse.model.*
+
+
+import groovy.transform.ExternalizeMethods
 
 buildscript {
   dependencies {
@@ -48,20 +52,18 @@ def compile_target_compatibility
 
 ext {
   // where the getdown channel will be built.
-  // TODO: consider allowing this expression to  be overrriden by -P arg
-  getdownWebsiteDir = jalviewDir + '/' + getdown_website_dir + '/' + JAVA_VERSION + '/'
+  // TODO: consider allowing this expression to  be overridden by -P arg
+  getdownWebsiteDir = jalviewDir + '/' + getdown_website_dir + '/' + JAVA_VERSION
   getdownAppDir = getdownWebsiteDir + '/' + getdown_app_dir
-  getdownJ11libDir = getdownWebsiteDir + '/' + getdown_j11lib_dir
+  //getdownJ11libDir = getdownWebsiteDir + '/' + getdown_j11lib_dir
   getdownResourceDir = getdownWebsiteDir + '/' + getdown_resource_dir
   getdownLauncher = jalviewDir + '/' + getdown_launcher
   getdownFilesDir = jalviewDir + '/' + getdown_files_dir + '/' + JAVA_VERSION + '/'
-  def getdownChannel = getdown_channel_name
-  if (getdown_channel_name.equals("COMMIT")) {
-    getdownChannel = getGitHash()
-  }
-  getdown_app_base = getdown_channel_base+"/"+getdownChannel+"/"+JAVA_VERSION+"/"
+  getdown_app_base = getdown_channel_base+"/"+getdown_channel_name+"/"+JAVA_VERSION+"/"
   modules_compileClasspath = fileTree(dir: "$jalviewDir/$j11modDir", include: ["*.jar"])
   modules_runtimeClasspath = modules_compileClasspath
+  gitHash = ""
+  gitBranch = ""
 }
 
 def JAVA_INTEGER_VERSION
@@ -70,14 +72,18 @@ def additional_compiler_args = []
 def getdown_alt_java_min_version
 // this property is assigned below and expanded to multiple lines in the getdown task
 def getdown_alt_multi_java_location
+// this property is for the Java library used in eclipse
+def eclipse_java_runtime_name
 if (JAVA_VERSION.equals("1.8")) {
   JAVA_INTEGER_VERSION = "8"
+  //libDir = j8libDir
   libDir = j11libDir
   libDistDir = j8libDir
   compile_source_compatibility = 1.8
   compile_target_compatibility = 1.8
   getdown_alt_java_min_version = getdown_alt_java8_min_version
   getdown_alt_multi_java_location = getdown_alt_java8_txt_multi_java_location
+  eclipse_java_runtime_name = "JavaSE-1.8"
 } else if (JAVA_VERSION.equals("11")) {
   JAVA_INTEGER_VERSION = "11"
   libDir = j11libDir
@@ -86,6 +92,7 @@ if (JAVA_VERSION.equals("1.8")) {
   compile_target_compatibility = 11
   getdown_alt_java_min_version = getdown_alt_java11_min_version
   getdown_alt_multi_java_location = getdown_alt_java11_txt_multi_java_location
+  eclipse_java_runtime_name = "JavaSE-11"
   additional_compiler_args += [
     '--module-path', ext.modules_compileClasspath.asPath,
     '--add-modules', j11modules
@@ -104,7 +111,6 @@ sourceSets {
 
     resources {
       srcDirs "$jalviewDir/$resourceDir"
-      srcDirs "$jalviewDir/$libDistDir"
     }
 
     jar.destinationDir = file("$jalviewDir/$packageDir")
@@ -149,8 +155,7 @@ sourceSets {
     } else {
       compileClasspath += files(sourceSets.main.java.outputDir)
     }
-    compileClasspath += sourceSets.main.compileClasspath
-    compileClasspath += files( sourceSets.main.resources.srcDirs)
+    
     compileClasspath += fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"])
     compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
 
@@ -190,7 +195,6 @@ eclipse {
         removeThese += it
       }
     }
-    containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
 
     minusConfigurations += removeThese
     plusConfigurations = [ ]
@@ -209,39 +213,21 @@ eclipse {
           }
         }
         cp.entries.removeAll(removeTheseToo)
-      }
-
-      withXml {
-        def node = it.asNode()
-        def srcTestAttributes
-        node.children().each{ cpe ->
-          def attributes = cpe.attributes()
-          if (attributes.get("kind") == "src" && attributes.get("path") == "test") {
-            srcTestAttributes = cpe.find { a -> a.name() == "attributes" }
-            return
-          }
-        }
-        def addTestAttribute = true
-        srcTestAttributes.each{a ->
-          if (a.name() == "attribute" && a.attributes().getAt("name") == "test") {
-            addTestAttribute = false
-          }
-        }
-        if (addTestAttribute) {
-          srcTestAttributes.append(new Node(null, "attribute", [name:"test", value:"true"]))
-        }
-
-        node.appendNode('classpathentry', [kind:"output", path:"bin/main"])
-        node.appendNode('classpathentry', [kind:"lib", path:helpParentDir])
-        node.appendNode('classpathentry', [kind:"lib", path:resourceDir])
+        
+        print ("CP="+cp.inspect())
+        
+        cp.entries += new Output("bin/main")
+        cp.entries += new Library(fileReference(helpParentDir))
+        cp.entries += new Library(fileReference(resourceDir))
+        
         HashMap<String, Boolean> addedLibPath = new HashMap<>();
-        def allPaths = sourceSets.test.compileClasspath + sourceSets.main.compileClasspath
-        sourceSets.main.compileClasspath.each{
-          //if ((it.isDirectory() || ! it.exists()) && ! (it.equals(sourceSets.main.java.outputDir))) {
-          //no longer want to add outputDir as eclipse is using its own output dir in bin/main
+        
+        // changing from sourcesets.main.classpath to specific Java version lib
+        //sourceSets.main.compileClasspath.each{
+        fileTree("$jalviewDir/$libDistDir").include("**/*.jar").include("*.jar").each {
+          //don't want to add outputDir as eclipse is using its own output dir in bin/main
           if (it.isDirectory() || ! it.exists()) {
             // don't add dirs to classpath
-            //println("Not adding directory "+it)
             return
           }
           def itPath = it.toString()
@@ -252,47 +238,82 @@ eclipse {
             //println("Not adding duplicate entry "+itPath)
           } else {
             //println("Adding entry "+itPath)
-            node.appendNode('classpathentry', [kind:"lib", path:itPath])
+            cp.entries += new Library(fileReference(itPath))
             addedLibPath.put(itPath, true)
           }
         }
-        sourceSets.test.compileClasspath.each{
+
+        // changing from sourcesets.main.classpath to specific Java version lib
+        //sourceSets.test.compileClasspath.each{
+        fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"]).each {
           //if ((it.isDirectory() || ! it.exists()) && ! (it.equals(sourceSets.main.java.outputDir))) {
           //no longer want to add outputDir as eclipse is using its own output dir in bin/main
           if (it.isDirectory() || ! it.exists()) {
             // don't add dirs to classpath
-            //println("Not adding directory "+it)
-            return
+            return false // groovy "break" in .each loop
           }
           def itPath = it.toString()
           if (itPath.startsWith(jalviewDirAbsolutePath+"/")) {
             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
           }
           if (addedLibPath.get(itPath)) {
-            //println("Not adding duplicate entry "+itPath)
+            // don't duplicate
           } else {
-            //println("Adding entry "+itPath)
-            node.appendNode('classpathentry', [kind:"lib", path:itPath])
-            .appendNode('attributes')
-            .appendNode('attribute', [name:"test", value:"true"])
+            def lib = new Library(fileReference(itPath))
+            // this doesn't work... yet.  Adding test=true attribute using withXml below
+            //def attrs = new Node(null, 'attributes', ["test":"true"])
+            //lib.appendNode(attrs) //
+            cp.entries += lib
             addedLibPath.put(itPath, true)
           }
         }
-      }
+      }  
 
-    }
-  }
+      // withXml changes ignored by buildship, these add the "test=true" attribute
+      withXml {
+        def node = it.asNode()
+        
+        def srcTestAttributes
+        node.children().each{ cpe ->
+          def attributes = cpe.attributes()
+          if (attributes.get("kind") == "src" && attributes.get("path") == "test") {
+            srcTestAttributes = cpe.find { a -> a.name() == "attributes" }
+            return
+          }
+        }
+        def addTestAttribute = true
+        srcTestAttributes.each{a ->
+          if (a.name() == "attribute" && a.attributes().getAt("name") == "test") {
+            addTestAttribute = false
+          }
+        }
+        if (addTestAttribute) {
+          srcTestAttributes.append(new Node(null, "attribute", [name:"test", value:"true"]))
+        }
+
+        node.children().each{ cpe ->
+          def attributes = cpe.attributes()
+          if (attributes.get("kind") == "lib" && attributes.get("path").startsWith("utils/")) {
+            cpe.appendNode('attributes')
+                .appendNode('attribute', [name:"test", value:"true"])
+          }
+        }
+      } // withXML
+    } // file
+
+    containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
+  } // classpath
 
   jdt {
     // for the IDE, use java 11 compatibility
-    sourceCompatibility = 11
-    targetCompatibility = 11
-    javaRuntimeName = "JavaSE-11"
+    sourceCompatibility = compile_source_compatibility
+    targetCompatibility = compile_target_compatibility
+    javaRuntimeName = eclipse_java_runtime_name
 
     file {
       withProperties { props ->
         def jalview_prefs = new Properties()
-        def ins = new FileInputStream(eclipse_extra_jdt_prefs_file)
+        def ins = new FileInputStream(jalviewDirAbsolutePath+"/"+eclipse_extra_jdt_prefs_file)
         jalview_prefs.load(ins)
         ins.close()
         jalview_prefs.forEach { t, v ->
@@ -303,8 +324,10 @@ eclipse {
       }
     }
   }
-
-}
+  
+  //synchronizationTasks eclipseClasspath
+  //autoBuildTasks eclipseClasspath
+} 
 
 task cloverInstr() {
   // only instrument source, we build test classes as normal
@@ -323,7 +346,7 @@ task cloverInstr() {
     com.atlassian.clover.CloverInstr.mainImpl(args)
   }
 }
-
+  
 
 task cloverReport {
   group = "Verification"
@@ -402,41 +425,76 @@ def getDate(format) {
   return date.format(format)
 }
 
-def getGitHash() {
-  def stdout = new ByteArrayOutputStream()
+task setGitVals {
+  def hashStdOut = new ByteArrayOutputStream()
   exec {
     commandLine "git", "rev-parse", "--short", "HEAD"
-    standardOutput = stdout
-    workingDir = jalviewDir
+    standardOutput = hashStdOut
+    ignoreExitValue true
   }
-  return stdout.toString().trim()
-}
 
-def getGitBranch() {
-  def stdout = new ByteArrayOutputStream()
+  def branchStdOut = new ByteArrayOutputStream()
   exec {
     commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
-    standardOutput = stdout
-    workingDir = jalviewDir
+    standardOutput = branchStdOut
+    ignoreExitValue true
   }
-  return stdout.toString().trim()
+
+  project.ext.gitHash = hashStdOut.toString().trim()
+  project.ext.gitBranch = branchStdOut.toString().trim()
+
+  outputs.upToDateWhen { false }
 }
 
 task createBuildProperties(type: WriteProperties) {
+  dependsOn setGitVals
   inputs.dir("$jalviewDir/$sourceDir")
+  inputs.dir("$classes")
   inputs.dir("$jalviewDir/$resourceDir")
   outputFile "$classes/$buildPropertiesFile"
-  /* taking time/date specific comment out to allow better incremental builds */
+  // taking time specific comment out to allow better incremental builds
   //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
   comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
   property "BUILD_DATE", getDate("dd MMMM yyyy")
   property "VERSION", JALVIEW_VERSION
-  property "INSTALLATION", INSTALLATION+" git-commit:"+getGitHash()+" ["+getGitBranch()+"]"
+  property "INSTALLATION", INSTALLATION+" git-commit:"+project.ext.gitHash+" ["+project.ext.gitBranch+"]"
   outputs.file(outputFile)
-  outputs.dir("$classes")
+}
+
+def buildingHTML = "$jalviewDir/$docDir/building.html"
+task deleteBuildingHTML(type: Delete) {
+  delete buildingHTML
+}
+
+task convertBuildingMD(type: Exec) {
+  dependsOn deleteBuildingHTML
+  def buildingMD = "$jalviewDir/$docDir/building.md"
+  def css = "$jalviewDir/$docDir/github.css"
+
+  def pandoc = pandoc_exec
+  def hostname = "hostname".execute().text.trim()
+  if (! file(pandoc).exists() && hostname.equals("jv-bamboo")) {
+    pandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
+  }
+
+  if (file(pandoc).exists()) {
+    commandLine pandoc, '-s', '-o', buildingHTML, '--metadata', 'pagetitle="Building Jalview from Source"', '--toc', '-H', css, buildingMD
+  } else {
+    commandLine "true"
+  }
+
+  ignoreExitValue true
+
+  inputs.file(buildingMD)
+  inputs.file(css)
+  outputs.file(buildingHTML)
+}
+clean {
+  delete buildingHTML
 }
 
 task syncDocs(type: Sync) {
+  dependsOn convertBuildingMD
   def syncDir = "$classes/$docDir"
   from fileTree("$jalviewDir/$docDir")
   into syncDir
@@ -538,6 +596,8 @@ task compileLinkCheck(type: JavaCompile) {
   destinationDir = file("$jalviewDir/$utilsDir")
   source = fileTree(dir: "$jalviewDir/$utilsDir", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
 
+  inputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.java")
+  inputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.java")
   outputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.class")
   outputs.file("$jalviewDir/$utilsDir/BufferedLineReader.class")
 }
@@ -550,7 +610,6 @@ task linkCheck(type: JavaExec) {
   workingDir = jalviewDir
   def help = "$classes/$helpDir"
   args = [ "$classes/$helpDir", "-nointernet" ]
-  //args = [ "$classesDir/$helpDir", "-nointernet" ]
 
   doFirst {
     helplinkscheckeroutputfile.createNewFile()
@@ -622,6 +681,7 @@ task cleanDist {
 }
 
 shadowJar {
+  group = "distribution"
   dependsOn makeDist
   from ("$jalviewDir/$libDistDir") {
     include("*.jar")
@@ -648,7 +708,7 @@ task getdownWebsite() {
     props.put("getdown_txt_multi_java_location", getdown_alt_multi_java_location)
 
     if (getdown_local == "true") {
-      getdown_app_base = "file://"+file(getdownWebsiteDir).getAbsolutePath()
+      getdown_app_base = file(getdownWebsiteDir).toURI().toString()
     }
     props.put("getdown_txt_appbase", getdown_app_base)
     props.each{ prop, val ->
@@ -846,15 +906,26 @@ task copyInstall4jTemplate(type: Copy) {
   outputs.files(install4jConf)
 
   doLast {
+    // include file associations in installer
     def installerFileAssociationsXml = file("$install4jDir/$install4jInstallerFileAssociations").text
     ant.replaceregexp(
       byline: false,
       flags: "s",
       match: '<action name="EXTENSIONS_REPLACED_BY_GRADLE".*?</action>',
-      //match: '<action.*?EXTENSIONS_REPLACED_BY_GRADLE.*?</action>',
       replace: installerFileAssociationsXml,
       file: install4jConf
     )
+    /*
+    // include uninstaller applescript app files in dmg
+    def installerDMGUninstallerXml = file("$install4jDir/$install4jDMGUninstallerAppFiles").text
+    ant.replaceregexp(
+      byline: false,
+      flags: "s",
+      match: '<file name="UNINSTALL_OLD_JALVIEW_APP_REPLACED_IN_GRADLE" file=.*?>',
+      replace: installerDMGUninstallerXml,
+      file: install4jConf
+    )
+    */
   }
 }
 
diff --git a/doc/building-OLD.html b/doc/building-OLD.html
deleted file mode 100755 (executable)
index f5e0b28..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-<html>
-<!--
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
- * This file is part of Jalview.
- * 
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- *  
- * Jalview is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty 
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
--->
-<head>
-<title>Building Jalview from Source</title>
-</head>
-<body>
-<h1>Building Jalview from Source</h1>
-<p/>
-
-<p>
-You will need the following:<br/>
-<ul>
-  <li> Obtain: git</li>
-  <li> Build/run: Java Development Kit (JDK). JDK11 is now the recommended platform for developing with Jalview.  You can obtain a pre-compiled JDK11 for many platforms from https://adoptopenjdk.net/</li>
-  <li> Build: Gradle 5.1 or later.  On linux you can obtain this with your package manager (e.g. <code>sudo yum install gradle</code> or <code>sudo apt install gradle</code> or on macOS with brew with <code>brew install gradle</code></li>
-</ul>
-With any luck, once you check out the Jalview source from git and set your JAVA_HOME and PATH correctly, you just need to change to the <code>jalview</code> directory and run <code>gradle getdown</code>.
-</p>
-
-<h2>Obtaining Jalview</h2>
-<p>This is easiest achieved with git:
-<pre>git clone http://www.jalview.org/git/jalview.git</pre>
-Then you can <code>cd jalview</code> to get into the top level jalview dir.
-
-
-<p>
-<h2>Minimal Jalview build</h2>
-<p>To run Jalview, you just need the jalview classes and the .jar libraries that Jalview depends on.</p>
-
-
-<!--
-<p>
-You will need the following (hopefully):<br>
-<ul>
-<li>Java development kit (JDK1.8 is now the recommended platform for developing with Jalview.</li>
-<li>Ant (1.7 or later will be needed for some of the jarsigning tools).</li>
-</ul>
-With any luck, after setting your paths and JAVA_HOME correctly, you
-just need to change to the Jalview directory and run ant (this works
-from eclipse too, but NetBeans is a bit trickier).
-<pre>
-   ant
-</pre>
-
-</p>
-<p><strong>Building a webstart version of jalview</strong></p>
-Jalview depends on several libraries contained in the libs directory
-of the distribution.  In order to access them, they must all be signed
-jars - using the same jarsigner key as jalview itself. There is a
-build target in ant to make the signed jar files in a directory called
-dist. But first you need to make your own key:
-<p><strong>Making your own key</strong></p>
-
-  <p>The ant 'makefulldist' target assumes that a keystore exists in
-    a directory 'keys'. To make a key accessible using the default
-    settings in the build.xml file then make the keys directory and add
-    the jarsigner key with the following :</p>
-  <pre>mkdir keys</pre>
-  <pre>keytool -genkey -keystore keys/.keystore -keypass alignmentisfun
-  -storepass alignmentisfun -sigalg SHA1withRSA -keyalg RSA -alias jalview</pre>
-  <em>(you will have to answer some personal questions here)</em>
-  <pre>ant makedist -DWebStartLocation="file://.pathtojalviewsource./dist" -Dapplication.codebase="*"</pre>
-  <p>This should eventually generate a jalview.jnlp file in ./dist
-    along with a set of signed jars using the jalview key). In order to
-    test locally via webstart you'll now need to add 'file:/' to your
-    java webstart security exception list. Then:</p>
-  <pre>javaws file://.pathtojalviewsource./dist/jalview.jnlp</pre>
-  <p>Please remember to remove that entry afterwards, since it will leave
-  your system vulnerable to malicious code.
-  </p>
-  <p>
-               <strong>Building the JalviewLite applet<br>
-               </strong> The JalviewLite applet is compiled using a subset of the packages in
-               the src directory (specifically: MCView, and jalview.{datamodel,
-               analysis, appletgui, utils, schemes, api, structure}, and
-               com.stevesoft.*). Once compiled, these class files are obfuscated to
-               make the code run efficiently. To compile the applet Jar, use the
-               makeApplet task - optionally passing in a 'donotobfuscate' property to
-               the ant build (e.g. -Ddonotobfuscate=true) to disable obfuscation. </p><p>
-               The ant target 'pubapplet' can be used to compile install the
-               jalviewApplet.jar and any dependent jars (under appletlib) into a copy
-               of the examples directory created under the <em>outputDir</em> build
-               property (which defaults to the 'dist' directory).
-       </p>
-       <p>
-<h1>using IDEs to build Jalview</h1>
-       <p>The Jalview source distribution includes project definitions for
-               Eclipse, Netbeans and some rather ancient Borland JBuilder .jpx
-               project files. These files should be sufficient to set up basic source
-               folders and build paths, but you will need to ensure that all .jar
-               files in the lib and appletlib directories are added to the build path
-               for your IDE project, and that the 'buildindices' target in Jalview's
-               build.xml is executed with the 'outputDir' ant property set to the
-               directory where the IDE expects to place compiled classes ('classes'
-               directory for eclipse, 'build/classes' for netbeans).</p>
-       <p>Note: It is generally not recommended that you distribute build
-               artefacts that were generated automatically via an IDE's own packaging
-               mechanism (e.g. Netbeans' executable Jar and dependent lib directory).
-               The hand-crafted ant build.xml is (currently) the only officially
-               supported method of building distributable versions of Jalview.</p>
-        -->
-<address>
-<a href="mailto:help@jalview.org">Jalview development team</a>
-</address>
-</body>
-</html>
diff --git a/doc/building.md b/doc/building.md
new file mode 100644 (file)
index 0000000..9648b9c
--- /dev/null
@@ -0,0 +1,493 @@
+# Building Jalview from Source
+
+## tl;dr
+
+```
+# download
+git clone http://source.jalview.org/git/jalview.git
+# compile
+cd jalview
+gradle shadowJar
+# run
+java -jar build/libs/jalview-all-11.jar
+
+# and/or create launcher
+gradle getdown
+# use launcher
+cd getdown/files
+java -jar getdown-launcher.jar . jalview
+```
+
+
+## Setting up
+
+The method here is described in terms of using a command line.  You can easily do this on linux or in a Terminal window in macOS.  You can do it in Windows.
+
+* Java 11 compliant JDK
+* gradle 5.1 or above
+* git
+
+> The versions and installation methods here are just suggestions (which we have tested 
+so are known to work).  If you need or wish to use different implementations (particularly 
+you might need a bespoke JDK if you are on an exotic architecture) then the general 
+build instructions should work with any gradle 5+.  You should be able to compile the 
+bytecode with any JDK Java 11+.  The resulting bytecode (in particular the shadow jar) 
+should be runnable in any JRE Java 1.8+.  Remember that because Jalview and the getdown launcher 
+are Java bytecode you can build on one system where you might have gradle, and run 
+on another where you don't (JRE 1.8+ required).
+
+### Java 11 compliant JDK
+
+#### All platforms
+We recommend obtaining an OpenJDK JDK 11 (since 11 is the long term support release) from AdoptOpenJDK: <https://adoptopenjdk.net/?variant=openjdk11&jvmVariant=hotspot>, either the *Installer* or `.zip`/`.tar.gz` variants whichever you prefer (if you're not sure, choose the *Installer*).
+
+>##### Alternative/CLI install of AdoptOpenJDK 11
+>
+>You can also install adoptopenjdk11 using either `brew` (macOS), `choco` (Windows)
+(see the section on `gradle` and `git` for more informaiton on `brew` and `choco`) 
+or `yum` or `apt` (Linux):
+>
+>###### alternative for MacOS and Homebrew
+>```
+>brew tap adoptopenjdk/openjdk
+>brew cask install adoptopenjdk11
+>```
+>
+>###### alternative for Windows and Chocolatey
+>```
+>choco install adoptopenjdk11
+>```
+>
+>###### alternative for Linux with yum/apt
+>
+>see <https://adoptopenjdk.net/installation.html#linux-pkg>
+
+
+### gradle and git
+You should be able to install the latest (or sufficiently recent) versions of gradle and git using your OS package manager.
+
+#### MacOS
+we recommend using `brew`, which can be installed following the instructions at <https://brew.sh/>.
+After installing `brew`, open a Terminal window and type in (using an Administrator privileged user):
+
+```bash
+brew install gradle git
+```
+
+or if you aready have them installed but need to upgrade the version:
+
+```bash
+brew upgrade gradle git
+```
+
+#### Windows
+
+we suggest using the **Chocolatey** package manager.  See install instructions at <https://chocolatey.org/>, and you will just need
+
+```bash
+choco install gradle
+choco install git
+```
+
+Alternatively, you could install a real `bash` shell and install both `gradle` and `git` through `apt-get`.
+See <https://devblogs.microsoft.com/commandline/bash-on-ubuntu-on-windows-download-now-3/> 
+for how to install the ubuntu bash shell in Windows 10.
+
+Another alternative would be to install them separately. For `gradle` follow the instructions at <https://gradle.org/install/>, and for `git` here are a couple of suggestions: Git for Windows <https://gitforwindows.org/>.
+Getting the individual installs working together on the command line will be trickier 
+so we recommend using Chocolatey or bash.
+
+
+#### Linux
+this will depend on which distribution you're using.
+
+##### For *Debian* based distributions (e.g. Mint, Ubuntu, Debian)
+run
+
+```bash
+ sudo apt-get install gradle git
+```
+
+##### for RPM-based distributions (e.g. Fedora, CentOS, RedHat)
+run
+
+```bash
+sudo yum install gradle git
+```
+
+If you have some other version of linux you'll probably be able to work it out!
+
+
+
+
+## Downloading the Jalview source tree
+
+This can be done with `git`.
+On the command line, change directory to where you want to download Jalview's build-tree 
+top level directory.  Then run
+
+```bash
+git clone http://source.jalview.org/git/jalview.git
+```
+
+You'll get some progress output and after a minute or two you should have the full 
+Jalview build-tree in the folder `jalview`.
+
+### What's in the source tree?
+
+Jalview is a mature product with its codebase going back many years.  As such it doesn't 
+have a folder structure that most new gradle projects would have, so you might not 
+find everything in the place you might expect.  Here's a brief description of what 
+you might find in the main folders under the `jalview` tree.
+
+Within the `jalview` folder you will find (of possible interest):
+
+  dir/ or file       | contains                                                   
+---------------------|----------------------------------------------------------------------------------------------------------------
+ `bin/`              | used by eclipse for compiled classes -- no need to touch this
+ `build/`            | the gradle build dir
+ `classes/`          | contains the compiled Java classes for the Jalview application
+ `dist/`             | assembled `.jar` files needed to run Jalview application
+ `examples/`         | example input files usable by Jalview
+ `getdown/`          | the libraries used by the Javliew launcher (getdown)
+ `getdown/src/`      | our modified source for `getdown`
+ `getdown/website/`  | the assembled "download" folder used by getdown for downloads/upgrades
+ `getdown/files/`    | the minimal fileset to launch the Jalview launcher, which can then download the rest of the Jalview application
+ `help/`             | the help documents
+ `j8lib/`            | libraries needed to run Jalview under Java 1.8
+ `j11lib/`           | libraries needed to run Jalivew under Java 11
+ `resource/`         | non-java resources used in the Jalview application
+ `src/`              | the Jalview application source `.java` files
+ `test/`             | Test class source files
+ `utils/`            | helper applications used in the build process
+ `utils/install4j/`  | files used by the packaging tool, install4j
+ `build.gradle`      | the build file used by gradle
+ `gradle.properties` | configurable properties for the build process
+
+Note that you need a Java 11 JDK to compile Jalview whether your target build is Java 1.8 or Java 11.
+
+
+## Building Jalview
+
+You will need to have the Java 11 `javac` in your path, or alternatively you can configure 
+gradle to know where this is by putting
+
+```
+org.gradle.java.home=/path_to_jdk_directory
+```
+in the `gradle.properties` file.
+
+> *You may want to see some of the other properties you can change at the end of this document.*
+
+### Minimal Jalview Build
+
+To compile the necessary class files, just run
+
+```bash
+gradle compileJava
+```
+to compile the classes into the `classes` folder.
+You should now be able to run the Jalview application directly with
+
+```bash
+java -cp "classes:resources:help:j11lib/*" jalview.bin.Jalview
+```
+
+You can also run with an automatic large memory setting (which will set the maximum 
+memory heap of the Jalview JVM to 90% of your local physical memory) and docked icon setting 
+(if possible in your OS) with
+
+```bash
+java -cp "classes:resources:help:j11lib/*" jalview.bin.Launcher
+```
+
+>*You must use just "`j11lib/*`" and not "`j11lib/*.jar`" as this is a special Java 
+classpath argument wildcard interpreted by `java`, **not** a shell expansion wildcard interpreted 
+by the shell.*
+
+Note that `jalview.bin.Launcher` is a simplified launcher class that re-launches `jalview.bin.Jalview` 
+with the same JRE (*not* the same JVM instance), classpath and arguments, but with an automatically determined `-Xmx...` 
+memory setting if one hasn't been provided.
+
+### Jalview in a Jar File
+
+To package the `classes`, `resources`, and `help` into one jar, you can run
+
+```bash
+gradle jar
+```
+which assembles the Jalview classes and resources into `dist/jalview.jar`
+
+To run this, use
+
+```bash
+java -cp "dist/jalview.jar:j11lib/*" jalview.bin.Jalview
+```
+
+### Distributed Jar Files
+
+To simplify this, all required `.jar` files can be assembled into the `dist` folder 
+using
+
+```bash
+gradle makeDist
+```
+which puts all required jar files into `dist` so you can run with
+
+```bash
+java -cp "dist/*" jalview.bin.Jalview
+```
+
+### Single *shadow* Jar File
+
+The shadow jar file is a single `.jar` that contains all required classes and resources from `jalview.jar` 
+and all of the supporting libraries in `j11lib/*.jar` merged into one `.jar` archive 
+file.  A default launching class (`MAIN-CLASS: jalview.bin.Launcher`) is specified in the `.jar` 
+manifest file (`META/MANIFEST.MF`) so a start class doesn't need to be specified.
+
+Build the shadow jar file in `build/lib/jalview-all-11.jar` with
+
+```bash
+gradle shadowJar
+```
+and run it with
+
+```bash
+java -jar build/lib/jalview-all-11.jar
+```
+
+Because no arguments are required, most OSes will associate a `.jar` file with the 
+`java` application (if this has been installed through the OS and not just a local 
+unzip) as a `-jar` argument so you may find you can launch `jalview-all-11.jar` 
+just by double-clicking on it)!
+
+> The `shadowJar` task is not a requirement for any other task, so to build the shadow 
+jar file you must specify the `shadowJar` task.
+
+> The shadow jar file represents probably the simplest way to distribute the Jalview application to machines that already have a Java 11 installed, 
+although without the many and compelling benefits of the `getdown` launcher.
+
+
+### Building the `getdown` launcher
+
+We have made significant customisations to the `getdown` launcher which you can find 
+in `getdown/src/getdown`.
+
+> You don't need to build this afresh as the required `gradle-core.jar` 
+and `gradle-launcher.jar` files are already distributed in `j11lib` and `getdown/lib` but if you want to, then 
+you'll need a working Maven and also a Java 8 JDK.  Ensure the Java 8 `javac` is forefront 
+in your path and do
+>
+>```bash
+>cd getdown/src/getdown
+>mvn clean package -Dgetdown.host.whitelist="jalview.org,*.jalview.org"
+>```
+> and you will find the required `.jar` files in `core/target/gradle-core-XXX.jar` 
+and `launcher/target/gradle-launcher-XXX.jar`.  The `gradle-core.jar` should then be copied 
+to all three of the `j8lib`, `j11lib` and `getdown/lib` folders, whilst the `gradle-launcher.jar` only 
+needs to be copied to `getdown/lib`.
+>
+>The `mvn` command should ideally include the `-Dgetdown.host.whitelist=*.jalview.org` setting. 
+ This, and the necessary file copying commands, can be found in `getdown/src/getdown/mvn_cmd`.
+
+To assemble Jalview with `getdown` use the following gradle task:
+
+```bash
+gradle getdown
+```
+
+This puts all the necessary files to launch Jalview with `getdown`
+into `getdown/website/11/`.  This could be treated as the reference folder 
+for `getdown`, which is where a getdown launcher will check to see if the Jalview application 
+files it has are up to date, and download if they aren't or it simply doesn't have 
+them.
+
+A minimal getdown-launcher can be found in `getdown/files/11/` which checks its up-to-date 
+status with (the absolute path to) `getdown/website/11/`.
+
+This can be launched with
+
+```bash
+java -jar getdown/files/11/getdown-launcher.jar getdown/files/11/ jalview
+```
+
+> We've already met the `-jar file.jar` arguments.  The next argument is the working folder for 
+getdown, and the final argument, "`jalview`", is a getdown application id (only "`jalview`" 
+is defined here).
+
+
+### Running tests
+
+There are substantial tests written for Jalview that use TestNG, which you can run with
+
+```bash
+gradle test
+```
+
+These normally take around 5 - 10 minutes to complete and outputs its full results into 
+the `tests/` folder.  A summary of results should appear in your console.
+
+
+### Installer packaging with *install4j*
+
+Jalview is currently using *install4j* <https://www.ej-technologies.com/products/install4j/overview.html> 
+as its installer packaging tool.
+
+If you have a licensed installation of *install4j* you can build Jalview installers 
+by running
+
+```bash
+gradle installers
+```
+
+though you may need to fiddle with the `install4j` and `copyInstall4jTemplate` tasks 
+in `build.gradle` file to point to your installation of *install4j* and also to bundled 
+JREs if you want to bundle those into the installers.
+
+If you want more details, get in touch on our development mailing list <jalview-dev@jalview.org>. 
+Sign up at <http://www.compbio.dundee.ac.uk/mailman/listinfo/jalview-dev>.
+
+
+## Building in Eclipse
+
+We develop in Eclipse, and support settings to develop and save Jalview source code 
+in our preferred style.  We also support running the Jalview application, debugging 
+and running tests with TestNG from within Eclipse.
+
+To get Jalview set up as a project in Eclipse, we recommend using at least the 2019-03 
+version of Eclipse IDE for Java Developers which you can download from the Eclipse 
+website: <https://www.eclipse.org/downloads/>
+
+Once installed, we also recommend installing several plugins from the Eclipse Marketplace.
+
+To do so, launch Eclipse, and go to Help->Eclipse Marketplace...
+
+Search for and install:
+
+1. Buildship Gradle Integration 3.0 (or greater)
+1. Groovy Development Tools 3.4.0 (or greater)
+1. TestNG for Eclipse (optional -- only needed if you want to run tests from Eclipse)
+
+> At time of writing, TestNG for Eclipse does not show up in the Eclipse Marketplace 
+as the latest released version does not install in Eclipse 2019-03.
+However, you can install a working beta of TestNG for Eclipse by going to
+>
+Help->Install New Software...
+>
+and entering
+>
+`TestNG Eclipse Composite P2 Repo - http://beust.com/eclipse-beta`
+>
+into the *Work with* box and click on the *Add...* button.
+>
+Eclipse might pause for a bit with the word *Pending* in the table below at this point, but it will eventually list TestNG with 
+a selection box under the *Name* column.
+>
+Select *TestNG* and carry on through the 
+install process to install the TestNG plugin.
+
+After installing the plugins, it is a good to get Java 11 set up in Eclipse as the default JRE.
+
+To do this go to Preferences (Eclipse->Preferences in macOS, File->Preferences 
+on Windows or Window->Preferences on Linux) and find
+
+Java -> Installed JREs
+
+If your Java 11 installation is not listed, click on
+
+*Add* -> Standard VM -> *Next*
+
+and enter the JRE home.  You can browse to where it was installed. Give it a name (like "AdoptOpenJDK 11").  Select this JDK 
+as the default JRE and click on *Apply and Close*.
+
+
+You can now import Jalview.  It is important to import 
+Jalview as a Gradle project (not as a Java project), so go to
+
+File->Import...
+
+find and select
+
+Gradle->Existing Gradle Project
+
+and then click on the *Next >* button.
+
+In the following options, it is the *Project Root Directory* you should set to be the 
+`jalview` folder that git downloaded.  Then you can click on the *Finish* button.
+
+
+## Gradle properties
+
+There are a lot of properties configured in `gradle.properties` which we strongly recommend 
+being left as they are unless you have a specific problem with the build process.
+
+There are a few gradle properties you might want to set on the command line with the 
+`-P` flag when building a version of Jalview with specific requirements:
+
+#### `JAVA_VERSION`
+This changes the *target* java bytecode version
+> NOTE that you will need to use a Java 11 (or greater) JDK Java compiler to build 
+Jalview for any byte-code target version.
+
+Valid values are `11` and `1.8`.
+
+e.g.
+
+```bash
+gradle shadowJar -PJAVA_VERSION=1.8
+```
+
+When using `-PJAVA_VERSION=1.8` the libraries from `j8lib` (instead of `j11lib`) will be used in the compile  
+and runtime classpath and also used in the `makeDist` build step.  Where a Java version of `11` is used in folder and file names, it will 
+instead use `1.8`.  Also if you are building installer packages with *install4j* the 
+package builder will look for JRE 1.8 bundles to package in the installers.
+
+> Note that continued development of Jalview will assume a Java 11+ runtime environment, 
+the 2.11.0 release will run under a Java 1.8 JRE with a few minor features disabled.
+
+#### `CHANNEL`
+This changes the `appbase` setting in `getdown.txt` (`appbase` is where the getdown launcher 
+looks to see if there's an updated file) to point to a particular Jalview 
+channel.  Expected values are `FILE`, `STABLE`, `DEVELOPMENT`, or a specific version 
+of Jalview like `2.11` or `2.10.5`.
+
+A value of `FILE` behaves differently to the other expected values and will use a local 
+file-system scheme URI instead of a Jalview release channel.  This `file:` scheme URI 
+uses an absolute path to the `getdown/website/<JAVA_VERSION>`
+
+On a regular development machine, this property will default to `LOCAL`.
+
+e.g.
+```bash
+gradle getdown -PCHANNEL=DEVELOPMENT
+```
+
+#### `MEDIA_TYPES`
+If you are building *install4j* installers (requires *install4j* to be installed) then this property specifies a comma-separated 
+list of media types (i.e. platform specific installers) *install4j* should actually build.
+
+Currently the valid values are
+`linuxDeb`, 
+`linuxRPM`, 
+`macosArchive`, 
+`unixArchive`, 
+`unixInstaller`, 
+`windows` 
+
+The default value is all of them.
+
+e.g.
+```bash
+gradle installers -PJAVA_VERSION=1.8 -PMEDA_TYPE=macosArchive
+```
+
+To get an up-to-date list of possible values, you can run
+
+```bash
+perl -n -e 'm/^\s*<(\w+)[^>]*\bmediaFileName=/ && print "$1\n";' utils/install4j/install4j_template.install4j  | sort -u
+```
+in the `jalview` root folder.
+
+
+---
+[Jalview Development Team](mailto:help@jalview.org)
\ No newline at end of file
diff --git a/doc/convert.sh b/doc/convert.sh
new file mode 100644 (file)
index 0000000..fbfa17d
--- /dev/null
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+pandoc -s -o building.html building.md --metadata pagetitle="Building Jalview from Source" --toc -H github.css
diff --git a/doc/github.css b/doc/github.css
new file mode 100644 (file)
index 0000000..9018d8a
--- /dev/null
@@ -0,0 +1,662 @@
+<style>
+@font-face {
+  font-family: octicons-link;
+  src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
+}
+
+body {
+  -webkit-text-size-adjust: 100%;
+  text-size-adjust: 100%;
+  color: #333;
+  font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+  font-size: 16px;
+  line-height: 1.6;
+  word-wrap: break-word;
+  width: 728px;
+  max-width: 99%;
+  box-sizing: border-box;
+  padding: 30px 30px 8rem 30px;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+body a {
+  background-color: transparent;
+}
+
+body a:active,
+body a:hover {
+  outline: 0;
+}
+
+body strong {
+  font-weight: bold;
+}
+
+body h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+body img {
+  border: 0;
+}
+
+body hr {
+  box-sizing: content-box;
+  height: 0;
+}
+
+body pre {
+  overflow: auto;
+}
+
+body code,
+body kbd,
+body pre {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+body input {
+  color: inherit;
+  font: inherit;
+  margin: 0;
+}
+
+body html input[disabled] {
+  cursor: default;
+}
+
+body input {
+  line-height: normal;
+}
+
+body input[type="checkbox"] {
+  box-sizing: border-box;
+  padding: 0;
+}
+
+body table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+body td,
+body th {
+  padding: 0;
+}
+
+body * {
+  box-sizing: border-box;
+}
+
+body input {
+  font: 13px / 1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+}
+
+body a {
+  color: #4078c0;
+  text-decoration: none;
+}
+
+body a:hover,
+body a:active {
+  text-decoration: underline;
+}
+
+body hr {
+  height: 0;
+  margin: 15px 0;
+  overflow: hidden;
+  background: transparent;
+  border: 0;
+  border-bottom: 1px solid #ddd;
+}
+
+body hr:before {
+  display: table;
+  content: "";
+}
+
+body hr:after {
+  display: table;
+  clear: both;
+  content: "";
+}
+
+body h1,
+body h2,
+body h3,
+body h4,
+body h5,
+body h6 {
+  margin-top: 15px;
+  margin-bottom: 15px;
+  line-height: 1.1;
+}
+
+body h1 {
+  font-size: 30px;
+}
+
+body h2 {
+  font-size: 21px;
+}
+
+body h3 {
+  font-size: 16px;
+}
+
+body h4 {
+  font-size: 14px;
+}
+
+body h5 {
+  font-size: 12px;
+}
+
+body h6 {
+  font-size: 11px;
+}
+
+body blockquote {
+  margin: 0;
+}
+
+body ul,
+body ol {
+  padding: 0;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+body ol ol,
+body ul ol {
+  list-style-type: lower-roman;
+}
+
+body ul ul ol,
+body ul ol ol,
+body ol ul ol,
+body ol ol ol {
+  list-style-type: lower-alpha;
+}
+
+body dd {
+  margin-left: 0;
+}
+
+body code {
+  font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  font-size: 12px;
+}
+
+body pre {
+  margin-top: 0;
+  margin-bottom: 0;
+  font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
+}
+
+body .select::-ms-expand {
+  opacity: 0;
+}
+
+body .octicon {
+  font: normal normal normal 16px/1 octicons-link;
+  display: inline-block;
+  text-decoration: none;
+  text-rendering: auto;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+
+body .octicon-link:before {
+  content: '\f05c';
+}
+
+body:before {
+  display: table;
+  content: "";
+}
+
+body:after {
+  display: table;
+  clear: both;
+  content: "";
+}
+
+body>*:first-child {
+  margin-top: 0 !important;
+}
+
+body>*:last-child {
+  margin-bottom: 0 !important;
+}
+
+body a:not([href]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+body .anchor {
+  display: inline-block;
+  padding-right: 2px;
+  margin-left: -18px;
+}
+
+body .anchor:focus {
+  outline: none;
+}
+
+body h1,
+body h2,
+body h3,
+body h4,
+body h5,
+body h6 {
+  margin-top: 1em;
+  margin-bottom: 16px;
+  font-weight: bold;
+  line-height: 1.4;
+}
+
+body h1 .octicon-link,
+body h2 .octicon-link,
+body h3 .octicon-link,
+body h4 .octicon-link,
+body h5 .octicon-link,
+body h6 .octicon-link {
+  color: #000;
+  vertical-align: middle;
+  visibility: hidden;
+}
+
+body h1:hover .anchor,
+body h2:hover .anchor,
+body h3:hover .anchor,
+body h4:hover .anchor,
+body h5:hover .anchor,
+body h6:hover .anchor {
+  text-decoration: none;
+}
+
+body h1:hover .anchor .octicon-link,
+body h2:hover .anchor .octicon-link,
+body h3:hover .anchor .octicon-link,
+body h4:hover .anchor .octicon-link,
+body h5:hover .anchor .octicon-link,
+body h6:hover .anchor .octicon-link {
+  visibility: visible;
+}
+
+body h1 {
+  padding-bottom: 0.3em;
+  font-size: 1.75em;
+  line-height: 1.2;
+}
+
+body h1 .anchor {
+  line-height: 1;
+}
+
+body h2 {
+  padding-bottom: 0.3em;
+  font-size: 1.5em;
+  line-height: 1.225;
+}
+
+body h2 .anchor {
+  line-height: 1;
+}
+
+body h3 {
+  font-size: 1.25em;
+  line-height: 1.43;
+}
+
+body h3 .anchor {
+  line-height: 1.2;
+}
+
+body h4 {
+  font-size: 1em;
+}
+
+body h4 .anchor {
+  line-height: 1.2;
+}
+
+body h5 {
+  font-size: 1em;
+}
+
+body h5 .anchor {
+  line-height: 1.1;
+}
+
+body h6 {
+  font-size: 1em;
+  color: #777;
+}
+
+body h6 .anchor {
+  line-height: 1.1;
+}
+
+body p,
+body blockquote,
+body ul,
+body ol,
+body dl,
+body table,
+body pre {
+  margin-top: 0;
+  margin-bottom: 16px;
+}
+
+body hr {
+  height: 4px;
+  padding: 0;
+  margin: 16px 0;
+  background-color: #e7e7e7;
+  border: 0 none;
+}
+
+body ul,
+body ol {
+  padding-left: 2em;
+}
+
+body ul ul,
+body ul ol,
+body ol ol,
+body ol ul {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+body li>p {
+  margin-top: 16px;
+}
+
+body dl {
+  padding: 0;
+}
+
+body dl dt {
+  padding: 0;
+  margin-top: 16px;
+  font-size: 1em;
+  font-style: italic;
+  font-weight: bold;
+}
+
+body dl dd {
+  padding: 0 16px;
+  margin-bottom: 16px;
+}
+
+body blockquote {
+  padding: 0 15px;
+  color: #777;
+  border-left: 4px solid #ddd;
+}
+
+body blockquote>:first-child {
+  margin-top: 0;
+}
+
+body blockquote>:last-child {
+  margin-bottom: 0;
+}
+
+body table {
+  display: block;
+  width: 100%;
+  overflow: auto;
+  word-break: normal;
+  word-break: keep-all;
+}
+
+body table th {
+  font-weight: bold;
+}
+
+body table th,
+body table td {
+  padding: 6px 13px;
+  border: 1px solid #ddd;
+}
+
+body table tr {
+  background-color: #fff;
+  border-top: 1px solid #ccc;
+}
+
+body table tr:nth-child(2n) {
+  background-color: #f8f8f8;
+}
+
+body img {
+  max-width: 100%;
+  box-sizing: content-box;
+  background-color: #fff;
+}
+
+body code {
+  padding: 0;
+  padding-top: 0;
+  padding-bottom: 0;
+  margin: 0;
+  font-size: 85%;
+  background-color: rgba(0,0,0,0.04);
+  border-radius: 3px;
+}
+
+body code:before,
+body code:after {
+  letter-spacing: -0.2em;
+  content: "\00a0";
+}
+
+body pre>code {
+  padding: 0;
+  margin: 0;
+  font-size: 100%;
+  word-break: normal;
+  white-space: pre;
+  background: transparent;
+  border: 0;
+}
+
+body .highlight {
+  margin-bottom: 16px;
+}
+
+body .highlight pre,
+body pre {
+  padding: 16px;
+  overflow: auto;
+  font-size: 85%;
+  line-height: 1.45;
+  background-color: #f7f7f7;
+  border-radius: 3px;
+}
+
+body .highlight pre {
+  margin-bottom: 0;
+  word-break: normal;
+}
+
+body pre {
+  word-wrap: normal;
+}
+
+body pre code {
+  display: inline;
+  max-width: initial;
+  padding: 0;
+  margin: 0;
+  overflow: initial;
+  line-height: inherit;
+  word-wrap: normal;
+  background-color: transparent;
+  border: 0;
+}
+
+body pre code:before,
+body pre code:after {
+  content: normal;
+}
+
+body kbd {
+  display: inline-block;
+  padding: 3px 5px;
+  font-size: 11px;
+  line-height: 10px;
+  color: #555;
+  vertical-align: middle;
+  background-color: #fcfcfc;
+  border: solid 1px #ccc;
+  border-bottom-color: #bbb;
+  border-radius: 3px;
+  box-shadow: inset 0 -1px 0 #bbb;
+}
+
+body .pl-c {
+  color: #969896;
+}
+
+body .pl-c1,
+body .pl-s .pl-v {
+  color: #0086b3;
+}
+
+body .pl-e,
+body .pl-en {
+  color: #795da3;
+}
+
+body .pl-s .pl-s1,
+body .pl-smi {
+  color: #333;
+}
+
+body .pl-ent {
+  color: #63a35c;
+}
+
+body .pl-k {
+  color: #a71d5d;
+}
+
+body .pl-pds,
+body .pl-s,
+body .pl-s .pl-pse .pl-s1,
+body .pl-sr,
+body .pl-sr .pl-cce,
+body .pl-sr .pl-sra,
+body .pl-sr .pl-sre {
+  color: #183691;
+}
+
+body .pl-v {
+  color: #ed6a43;
+}
+
+body .pl-id {
+  color: #b52a1d;
+}
+
+body .pl-ii {
+  background-color: #b52a1d;
+  color: #f8f8f8;
+}
+
+body .pl-sr .pl-cce {
+  color: #63a35c;
+  font-weight: bold;
+}
+
+body .pl-ml {
+  color: #693a17;
+}
+
+body .pl-mh,
+body .pl-mh .pl-en,
+body .pl-ms {
+  color: #1d3e81;
+  font-weight: bold;
+}
+
+body .pl-mq {
+  color: #008080;
+}
+
+body .pl-mi {
+  color: #333;
+  font-style: italic;
+}
+
+body .pl-mb {
+  color: #333;
+  font-weight: bold;
+}
+
+body .pl-md {
+  background-color: #ffecec;
+  color: #bd2c00;
+}
+
+body .pl-mi1 {
+  background-color: #eaffea;
+  color: #55a532;
+}
+
+body .pl-mdr {
+  color: #795da3;
+  font-weight: bold;
+}
+
+body .pl-mo {
+  color: #1d3e81;
+}
+
+body kbd {
+  display: inline-block;
+  padding: 3px 5px;
+  font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  line-height: 10px;
+  color: #555;
+  vertical-align: middle;
+  background-color: #fcfcfc;
+  border: solid 1px #ccc;
+  border-bottom-color: #bbb;
+  border-radius: 3px;
+  box-shadow: inset 0 -1px 0 #bbb;
+}
+
+body .task-list-item {
+  list-style-type: none;
+}
+
+body .task-list-item+.task-list-item {
+  margin-top: 3px;
+}
+
+body .task-list-item input {
+  margin: 0 0.35em 0.25em -1.6em;
+  vertical-align: middle;
+}
+
+body :checked+.radio-label {
+  z-index: 1;
+  position: relative;
+  border-color: #4078c0;
+}
+</style>
index 7230883..4a90866 100644 (file)
Binary files a/getdown/lib/getdown-core-1.8.3-SNAPSHOT.jar and b/getdown/lib/getdown-core-1.8.3-SNAPSHOT.jar differ
index cb5f670..aeb6e0c 100644 (file)
Binary files a/getdown/lib/getdown-launcher.jar and b/getdown/lib/getdown-launcher.jar differ
index 25cd109..0de5c8a 100644 (file)
@@ -26,6 +26,7 @@ import java.util.zip.GZIPInputStream;
 import com.sun.management.OperatingSystemMXBean;
 import java.lang.management.ManagementFactory;
 
+import jalview.bin.MemorySetting;
 
 import com.threerings.getdown.util.*;
 // avoid ambiguity with java.util.Base64 which we can't use as it's 1.8+
@@ -753,28 +754,34 @@ public class Application
             jvmmempc = config.getInt(appPrefix + "jvmmempc", jvmmempc);
         }
         if (0 <= jvmmempc && jvmmempc <= 100) {
-            final Object o = ManagementFactory.getOperatingSystemMXBean();
-
-            try {
-                if (o instanceof OperatingSystemMXBean) {
-                    final OperatingSystemMXBean osb = (OperatingSystemMXBean) o;
-                    long physicalMem = osb.getTotalPhysicalMemorySize();
-                    long requestedMem = physicalMem*jvmmempc/100;
-                    String[] maxMemHeapArg = new String[]{"-Xmx"+Long.toString(requestedMem)};
-                    // remove other max heap size arg
-                    ARG: for (int i = 0; i < _jvmargs.size(); i++) {
-                           if (_jvmargs.get(i) instanceof java.lang.String && _jvmargs.get(i).startsWith("-Xmx")) {
-                                _jvmargs.remove(i);
-                           }
-                    }
-                    addAll(maxMemHeapArg, _jvmargs);
+          
+          long maxMemLong = -1;
+
+          try
+          {
+            maxMemLong = MemorySetting.memPercent(jvmmempc);
+          } catch (Exception e)
+          {
+            e.printStackTrace();
+          } catch (Throwable t)
+          {
+            t.printStackTrace();
+          }
 
-                }
-            }
-            catch (NoClassDefFoundError e) {
-                // com.sun.management.OperatingSystemMXBean doesn't exist in this JVM
-                System.out.println("No com.sun.management.OperatingSystemMXBean. Cannot use 'jvmmempc'.");
+          if (maxMemLong > 0)
+          {
+            
+            String[] maxMemHeapArg = new String[]{"-Xmx"+Long.toString(maxMemLong)};
+            // remove other max heap size arg
+            ARG: for (int i = 0; i < _jvmargs.size(); i++) {
+              if (_jvmargs.get(i) instanceof java.lang.String && _jvmargs.get(i).startsWith("-Xmx")) {
+                _jvmargs.remove(i);
+              }
             }
+            addAll(maxMemHeapArg, _jvmargs);
+            
+          }
+
         } else if (jvmmempc != -1) {
           System.out.println("'jvmmempc' value must be in range 0 to 100 (read as '"+Integer.toString(jvmmempc)+"')");
         }
diff --git a/getdown/src/getdown/core/src/main/java/jalview/bin/MemorySetting.java b/getdown/src/getdown/core/src/main/java/jalview/bin/MemorySetting.java
new file mode 100644 (file)
index 0000000..b3bae2d
--- /dev/null
@@ -0,0 +1,51 @@
+package jalview.bin;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+
+public class MemorySetting
+{
+  public static final long leaveFreeMinMemory = 536870912; // 0.5 GB
+
+  public static final long applicationMinMemory = 536870912; // 0.5 GB
+
+  protected static long getPhysicalMemory()
+  {
+    final OperatingSystemMXBean o = ManagementFactory
+            .getOperatingSystemMXBean();
+
+    try
+    {
+      if (o instanceof com.sun.management.OperatingSystemMXBean)
+      {
+        final com.sun.management.OperatingSystemMXBean osb = (com.sun.management.OperatingSystemMXBean) o;
+        return osb.getTotalPhysicalMemorySize();
+      }
+    } catch (NoClassDefFoundError e)
+    {
+      // com.sun.management.OperatingSystemMXBean doesn't exist in this JVM
+      System.out.println("No com.sun.management.OperatingSystemMXBean");
+    }
+
+    // We didn't get a com.sun.management.OperatingSystemMXBean.
+    return -1;
+  }
+
+  public static long memPercent(int percent)
+  {
+    long memPercent = -1;
+
+    long physicalMem = getPhysicalMemory();
+    if (physicalMem > applicationMinMemory)
+    {
+      // try and set at least applicationMinMemory and thereafter ensure
+      // leaveFreeMinMemory is left for the OS
+      memPercent = Math.max(applicationMinMemory,
+              physicalMem - Math.max(physicalMem * (100 - percent) / 100,
+                      leaveFreeMinMemory));
+    }
+
+    return memPercent;
+  }
+
+}
index 66629f2..539b47e 100644 (file)
@@ -807,10 +807,10 @@ public abstract class Getdown extends Thread
         if (_ifc.rotatingBackgrounds != null) {
             if (_ifc.backgroundImage != null) {
                 log.warning("ui.background_image and ui.rotating_background were both specified. " +
-                            "The rotating images are being used.");
+                            "The background image is being used.");
             }
-            return new RotatingBackgrounds(_ifc.rotatingBackgrounds, _ifc.errorBackground,
-                Getdown.this);
+            return new RotatingBackgrounds(loadImage(_ifc.backgroundImage));
+            //return new RotatingBackgrounds(_ifc.rotatingBackgrounds, _ifc.errorBackground, Getdown.this);
         } else if (_ifc.backgroundImage != null) {
             return new RotatingBackgrounds(loadImage(_ifc.backgroundImage));
         } else {
index d984902..0ce786f 100644 (file)
@@ -1 +1 @@
-mvn clean package -Dgetdown.host.whitelist=jalview.org,*.jalview.org && cp launcher/target/getdown-launcher-1.8.3-SNAPSHOT.jar ../../../getdown/lib/getdown-launcher.jar && cp core/target/getdown-core-1.8.3-SNAPSHOT.jar ../../../getdown/lib/getdown-core-1.8.3-SNAPSHOT.jar && cp core/target/getdown-core-1.8.3-SNAPSHOT.jar ../../../j8lib/getdown-core.jar && cp core/target/getdown-core-1.8.3-SNAPSHOT.jar ../../../j11lib/getdown-core.jar 
+mvn clean package -Dgetdown.host.whitelist="jalview.org,*.jalview.org" && cp launcher/target/getdown-launcher-1.8.3-SNAPSHOT.jar ../../../getdown/lib/getdown-launcher.jar && cp core/target/getdown-core-1.8.3-SNAPSHOT.jar ../../../getdown/lib/getdown-core-1.8.3-SNAPSHOT.jar && cp core/target/getdown-core-1.8.3-SNAPSHOT.jar ../../../j8lib/getdown-core.jar && cp core/target/getdown-core-1.8.3-SNAPSHOT.jar ../../../j11lib/getdown-core.jar 
index e49c3ab..f5c6f49 100644 (file)
@@ -1,5 +1,6 @@
 jalviewDir = .
 
+#JAVA_VERSION = 1.8
 JAVA_VERSION = 11
 JALVIEW_VERSION = DEVELOPMENT
 INSTALLATION = Source
@@ -15,9 +16,6 @@ jalview_keydig = SHA1
 
 testngGroups = Functional
 
-javac_source = 11
-javac_target = 11
-
 j8libDir = j8lib
 j11libDir = j11lib
 resourceDir = resources
@@ -50,7 +48,7 @@ getdown_local = false
 getdown_website_dir = getdown/website
 getdown_resource_dir = resource
 getdown_app_dir = dist
-getdown_j11lib_dir = j11lib
+#getdown_j11lib_dir = j11lib
 getdown_files_dir = getdown/files
 getdown_launcher = getdown/lib/getdown-launcher.jar
 getdown_core = getdown/lib/getdown-core-1.8.3-SNAPSHOT.jar
@@ -59,7 +57,7 @@ getdown_txt_title = Jalview
 getdown_channel_base = http://www.jalview.org/getdown/jalview
 getdown_channel_name = TEST
 getdown_txt_allow_offline = true
-getdown_txt_jvmmempc = 95
+getdown_txt_jalview.jvmmempc = 90
 getdown_txt_multi_jvmarg = -Dgetdownappdir="%APPDIR%"
 getdown_txt_strict_comments = true
 getdown_txt_title = Jalview
@@ -100,8 +98,8 @@ install4jResourceDir = utils/install4j
 install4jTemplate = install4j_template.install4j
 install4jInfoPlistFileAssociations = file_associations_auto-Info_plist.xml
 install4jInstallerFileAssociations = file_associations_auto-install4j.xml
+install4jDMGUninstallerAppFiles = uninstall_old_jalview_files.xml
 install4jBuildDir = build/install4j
-install4jMediaTypes = windows,macosArchive,linuxRPM,linuxDeb,unixArchive
 install4jMediaTypes = windows,macosArchive,linuxRPM,linuxDeb,unixArchive,unixInstaller
 install4jFaster = false
 
@@ -111,5 +109,6 @@ JSIGN_SH = echo
 
 eclipse_extra_jdt_prefs_file = .settings/org.eclipse.jdt.core.jalview.prefs
 
+pandoc_exec = /usr/local/bin/pandoc
 dev = false
 
index a98b060..e7b2f47 100755 (executable)
@@ -58,7 +58,7 @@ li:before {
     <tr>
       <td width="60" align="center" nowrap>
           <strong><a name="Jalview.2.11">2.11</a><br />
-            <em>14/05/2019 (final due date !)</em></strong>
+            <em>tbc/06/2019</em></strong>
       </td>
       <td align="left" valign="top">
         <ul>
@@ -134,7 +134,7 @@ li:before {
           <li>
             <!-- JAL-2975 -->Can use shift + arrow keys to rotate PCA image incrementally</li>
           <li>
-            <!-- JAL-2965 -->PCA depth queuing with graduated colours</li>
+            <!-- JAL-2965 -->PCA depth cueing with graduated colours</li>
         </ul>
         <em>Deprecations</em>
         <ul>
index 7230883..4a90866 100644 (file)
Binary files a/j11lib/getdown-core.jar and b/j11lib/getdown-core.jar differ
index 7230883..4a90866 100644 (file)
Binary files a/j8lib/getdown-core.jar and b/j8lib/getdown-core.jar differ
index 04e8982..f095290 100644 (file)
@@ -1354,12 +1354,13 @@ label.append_to_filename = Append to filename (%n is replaced by the backup numb
 label.append_to_filename_tooltip = %n in the text will be replaced by the backup number. The text will appear after the filename. See the summary box above.
 label.index_digits = Number of digits to use for the backup number (%n)
 label.summary_of_backups_scheme = Summary of backup scheme
+label.scheme_examples = Scheme examples
 label.increment_index = Increase appended text numbers - newest file has largest number.
 label.reverse_roll = "Roll" appended text numbers - newest backup file is always number 1.
 label.keep_files = Deleting old backup files
 label.keep_all_backup_files = Do not delete old backup files
 label.keep_only_this_number_of_backup_files = Keep only this number of most recent backup files
-label.autodelete_old_backup_files = Autodelete old backup files:
+label.autodelete_old_backup_files = Auto-delete old backup files:
 label.always_ask = Always ask
 label.auto_delete = Automatically delete
 label.filename = filename
@@ -1369,10 +1370,18 @@ label.configuration = Configuration
 label.configure_feature_tooltip = Click to configure variable colour or filters
 label.schemes = Schemes
 label.customise = Customise
+label.custom = Custom
 label.default = Default
 label.single_file = Single backup
 label.keep_all_versions = Keep all versions
 label.rolled_backups = Rolled backup files
+label.customise_description = Select Customise, make changes, and click on OK to save your own custom scheme
+label.custom_description = Your own saved scheme
+label.default_description = Keep the last three versions of the file
+label.single_file_description = Keep the last version of the file
+label.keep_all_versions_description = Keep all previous versions of the file
+label.rolled_backups_description = Keep the last nine versions of the file from _bak.1 (newest) to _bak.9 (oldest)
+label.cancel_changes_description = Cancel changes made to your last saved Custom scheme
 label.previously_saved_scheme = Previously saved scheme
 label.no_backup_files = NO BACKUP FILES
 label.include_backup_files = Include backup files
index 9efeca1..ec7eb5d 100644 (file)
@@ -32,7 +32,7 @@ action.load_project = Cargar proyecto
 action.save_project = Guardar proyecto
 action.save_project_as = Guardar proyecto como...
 action.quit = Salir
-label.quit_jalview = Salir Javliew?
+label.quit_jalview = Salir de Jalview?
 action.expand_views = Expandir vistas
 action.gather_views = Capturar vistas
 action.page_setup = Configuración de la página
@@ -1355,6 +1355,7 @@ label.append_to_filename = Adjuntar texto (%n es reemplazado por el n
 label.append_to_filename_tooltip = %n en el texto será reemplazado por el número de respaldo. El texto será después del nombre del archivo. Vea el cuadro de resumen arriba.
 label.index_digits = Número de dígitos a utilizar para el número de respaldo.
 label.summary_of_backups_scheme = Resumen del esquema de copias de seguridad
+label.scheme_examples = Ejemplos de esquema
 label.increment_index = Aumente los números de texto adjuntos: el archivo más nuevo tiene el número más grande
 label.reverse_roll = Ciclos de texto adjuntos: el respaldo más reciente es siempre el número 1
 label.keep_files = Borrando los respaldos antiguos
@@ -1369,11 +1370,19 @@ label.braced_newest = (mas nuevo)
 label.configuration = Configuración
 label.configure_feature_tooltip = Haga clic para configurar el color o los filtros
 label.schemes = Esquemas
-label.customise = Personalizado
+label.customise = Personalizar
+label.custom = Personal
 label.default = Defecto
 label.single_file = Solo uno respaldo
 label.keep_all_versions = Mantener todas las versiones
 label.rolled_backups = Ciclos respaldos
+label.customise_description = Seleccione Personalizar, haga cambios y haga clic en OK para guardar su propio esquema personalizado
+label.custom_description = Tu propio esquema guardado
+label.default_description = Conserve las Ãºltimas tres versiones del archivo
+label.single_file_description = Conserve la Ãºltima versión del archivo
+label.keep_all_versions_description = Mantener todas las versiones anteriores del archivo
+label.rolled_backups_description = Mantenga las Ãºltimas nueve versiones del archivo desde _bak.1 (más reciente) a _bak.9 (más antigua)
+label.cancel_changes_description = Cancelar los cambios realizados en su Ãºltimo esquema personalizado guardado
 label.previously_saved_scheme = Esquema previamente guardado
 label.no_backup_files = NO ARCHIVOS DE RESPALDOS
 label.include_backup_files = Incluir archivos de respaldos
index 07dee98..1d2235e 100755 (executable)
                                                                </xs:documentation>
                                                        </xs:annotation>
                                                </xs:attribute>
+                                               <xs:attribute name="showComplementFeatures" type="xs:boolean" use="optional" default="false" />
+                                               <xs:attribute name="showComplementFeaturesOnTop" type="xs:boolean" use="optional" default="false" />
                                        </xs:complexType>
                                </xs:element>
                                <xs:element name="UserColours" minOccurs="0" maxOccurs="unbounded">
index 22b7aac..20c19dd 100755 (executable)
                                                        </xs:element>
                                                </xs:choice>
                                        </xs:sequence>
+                                       <xs:attribute name="mappingType" type="xs:string" use="optional">
+                                               <xs:annotation>
+                                                       <xs:documentation>Biotype of the mapping e.g. CdsToPeptide</xs:documentation>
+                                               </xs:annotation>
+                                       </xs:attribute>
                                </xs:extension>
                        </xs:complexContent>    
                </xs:complexType>
                                                                <xs:attribute name="source" type="xs:string"/>
                                                                <xs:attribute name="version" type="xs:string"/>
                                                                <xs:attribute name="accessionId" type="xs:string"/>
+                                                               <xs:attribute name="locus" type="xs:boolean" default="false">
+                                                                       <xs:annotation>
+                                                                               <xs:documentation>
+                                                                                       true for gene locus mapping, source=species, version=assembly, accession=chromosome
+                                                                               </xs:documentation>
+                                                                       </xs:annotation>
+                                                               </xs:attribute>
                                                        </xs:complexType>
                                                </xs:element>
                                        </xs:sequence>
                                                        </xs:documentation>
                                                </xs:annotation>
                                        </xs:attribute>
+                                       <xs:attribute name="biotype" type="xs:string" use="optional">
+                                               <xs:annotation>
+                                                       <xs:documentation>
+                                                               Biotype of the sequence (if known)
+                                                       </xs:documentation>
+                                               </xs:annotation>
+                                       </xs:attribute>
                                </xs:extension>
                        </xs:complexContent>
                </xs:complexType>
index 0dfd383..0bc8180 100644 (file)
@@ -1870,7 +1870,7 @@ public class AlignmentUtils
       return;
     }
 
-    MapList newMap = targetToFrom.traverse(fromLoci.getMap());
+    MapList newMap = targetToFrom.traverse(fromLoci.getMapping());
 
     if (newMap != null)
     {
index c66e63e..449c1fb 100755 (executable)
@@ -360,10 +360,12 @@ public class Jalview
         JalviewTaskbar.setTaskbar(this);
       } catch (Exception e)
       {
-        e.printStackTrace();
+        System.out.println("Cannot set Taskbar");
+        // e.printStackTrace();
       } catch (Throwable t)
       {
-        t.printStackTrace();
+        System.out.println("Cannot set Taskbar");
+        // t.printStackTrace();
       }
 
       desktop.setVisible(true);
index 5747263..7dd0382 100644 (file)
@@ -29,7 +29,7 @@ public class JalviewTaskbar
           }
         } catch (Exception e)
         {
-          e.printStackTrace();
+          System.out.println("Unable to setIconImage()");
         }
       }
     }
index aec3acd..412f119 100644 (file)
@@ -1,8 +1,8 @@
 package jalview.bin;
 
 import java.io.File;
+import java.io.IOException;
 import java.lang.management.ManagementFactory;
-import java.lang.management.OperatingSystemMXBean;
 import java.util.ArrayList;
 
 public class Launcher
@@ -10,7 +10,9 @@ public class Launcher
 
   private final static String startClass = "jalview.bin.Jalview";
 
-  private final static int maxHeapSizePerCent = 95;
+  private final static int maxHeapSizePerCent = 90;
+
+  private final static String maxHeapSizePerCentProperty = "jvmmempc";
 
   private final static String dockIconPath = "JalviewLogo_Huge.png";
 
@@ -22,6 +24,8 @@ public class Launcher
     ArrayList<String> command = new ArrayList<>();
     command.add(javaBin);
 
+    String memSetting = null;
+
     boolean isAMac = System.getProperty("os.name").indexOf("Mac") > -1;
 
     for (String jvmArg : ManagementFactory.getRuntimeMXBean()
@@ -40,39 +44,81 @@ public class Launcher
     // add memory setting if not specified
     boolean memSet = false;
     boolean dockIcon = false;
+    boolean dockName = false;
     ARG: for (int i = 0; i < command.size(); i++)
     {
       String arg = command.get(i);
       if (arg.startsWith("-Xmx"))
       {
+        memSetting = arg;
         memSet = true;
       }
       else if (arg.startsWith("-Xdock:icon"))
       {
         dockIcon = true;
       }
+      else if (arg.startsWith("-Xdock:name"))
+      {
+        dockName = true;
+      }
     }
 
     if (!memSet)
     {
       long maxMemLong = -1;
-      long physicalMem = getPhysicalMemory();
-      if (physicalMem > 0)
+      int percent = maxHeapSizePerCent;
+      String jvmmempc = System.getProperty(maxHeapSizePerCentProperty);
+      try
+      {
+        if (jvmmempc != null)
+        {
+          int trypercent = Integer.parseInt(jvmmempc);
+          if (0 < trypercent && trypercent <= 100)
+          {
+            percent = trypercent;
+          }
+          else
+          {
+            System.out.println("Property '" + maxHeapSizePerCentProperty
+                    + "' should be in range 1..100");
+          }
+        }
+      } catch (Exception e)
+      {
+        System.out.println("Error parsing " + maxHeapSizePerCentProperty
+                + " '" + jvmmempc + "'");
+      }
+
+      try
       {
-        maxMemLong = physicalMem * maxHeapSizePerCent / 100;
+        maxMemLong = MemorySetting.memPercent(percent);
+      } catch (Exception e)
+      {
+        e.printStackTrace();
+      } catch (Throwable t)
+      {
+        t.printStackTrace();
       }
+
       if (maxMemLong > 0)
       {
-        command.add("-Xmx" + Long.toString(maxMemLong));
+        memSetting = "-Xmx" + Long.toString(maxMemLong);
+        command.add(memSetting);
       }
     }
 
-    if (!dockIcon && isAMac)
+    if (isAMac)
     {
-      command.add("-Xdock:icon=" + dockIconPath);
-      // -Xdock:name=... doesn't actually work :(
-      // Leaving it in in case it gets fixed
-      command.add("-Xdock:name=" + "Jalview");
+      if (!dockIcon)
+      {
+        command.add("-Xdock:icon=" + dockIconPath);
+      }
+      if (!dockName)
+      {
+        // -Xdock:name=... doesn't actually work :(
+        // Leaving it in in case it gets fixed
+        command.add("-Xdock:name=" + "Jalview");
+      }
     }
 
     command.add(startClass);
@@ -80,41 +126,53 @@ public class Launcher
 
     final ProcessBuilder builder = new ProcessBuilder(command);
 
-    System.out.println("COMMAND: " + String.join(" ", builder.command()));
+    // System.out.println("COMMAND: " + String.join(" ", builder.command()));
+    System.out.println("Running " + startClass + " with "
+            + (memSetting == null ? "no memSetting" : memSetting));
 
     try
     {
       builder.inheritIO();
       Process process = builder.start();
       process.waitFor();
-    } catch (Exception e)
+    } catch (IOException e)
     {
-      e.printStackTrace();
-    }
-    // System.exit(0);
-
-  }
-
-  public static long getPhysicalMemory()
-  {
-    final OperatingSystemMXBean o = ManagementFactory
-            .getOperatingSystemMXBean();
-
-    try
-    {
-      if (o instanceof com.sun.management.OperatingSystemMXBean)
+      if (e.getMessage().toLowerCase().contains("memory"))
+      {
+        System.out.println("Caught a memory exception: " + e.getMessage());
+        // Probably the "Cannot allocate memory" error, try without the memory setting
+        ArrayList<String> commandNoMem = new ArrayList<>();
+        for (int i = 0; i < command.size(); i++)
+        {
+          if (!command.get(i).startsWith("-Xmx"))
+          {
+            commandNoMem.add(command.get(i));
+          }
+        }
+        final ProcessBuilder builderNoMem = new ProcessBuilder(
+                commandNoMem);
+        System.out.println("NO MEM COMMAND: "
+                + String.join(" ", builderNoMem.command()));
+        try
+        {
+          builderNoMem.inheritIO();
+          Process processNoMem = builderNoMem.start();
+          processNoMem.waitFor();
+        } catch (Exception ex)
+        {
+          ex.printStackTrace();
+        }
+      }
+      else
       {
-        final com.sun.management.OperatingSystemMXBean osb = (com.sun.management.OperatingSystemMXBean) o;
-        return osb.getTotalPhysicalMemorySize();
+        e.printStackTrace();
       }
-    } catch (NoClassDefFoundError e)
+    } catch (Exception e)
     {
-      // com.sun.management.OperatingSystemMXBean doesn't exist in this JVM
-      System.out.println("No com.sun.management.OperatingSystemMXBean");
+      e.printStackTrace();
     }
+    // System.exit(0);
 
-    // We didn't get a com.sun.management.OperatingSystemMXBean.
-    return -1;
   }
 
 }
diff --git a/src/jalview/bin/MemorySetting.java b/src/jalview/bin/MemorySetting.java
new file mode 100644 (file)
index 0000000..b3bae2d
--- /dev/null
@@ -0,0 +1,51 @@
+package jalview.bin;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+
+public class MemorySetting
+{
+  public static final long leaveFreeMinMemory = 536870912; // 0.5 GB
+
+  public static final long applicationMinMemory = 536870912; // 0.5 GB
+
+  protected static long getPhysicalMemory()
+  {
+    final OperatingSystemMXBean o = ManagementFactory
+            .getOperatingSystemMXBean();
+
+    try
+    {
+      if (o instanceof com.sun.management.OperatingSystemMXBean)
+      {
+        final com.sun.management.OperatingSystemMXBean osb = (com.sun.management.OperatingSystemMXBean) o;
+        return osb.getTotalPhysicalMemorySize();
+      }
+    } catch (NoClassDefFoundError e)
+    {
+      // com.sun.management.OperatingSystemMXBean doesn't exist in this JVM
+      System.out.println("No com.sun.management.OperatingSystemMXBean");
+    }
+
+    // We didn't get a com.sun.management.OperatingSystemMXBean.
+    return -1;
+  }
+
+  public static long memPercent(int percent)
+  {
+    long memPercent = -1;
+
+    long physicalMem = getPhysicalMemory();
+    if (physicalMem > applicationMinMemory)
+    {
+      // try and set at least applicationMinMemory and thereafter ensure
+      // leaveFreeMinMemory is left for the OS
+      memPercent = Math.max(applicationMinMemory,
+              physicalMem - Math.max(physicalMem * (100 - percent) / 100,
+                      leaveFreeMinMemory));
+    }
+
+    return memPercent;
+  }
+
+}
index 98868ce..bc8d0cf 100755 (executable)
@@ -27,15 +27,6 @@ import java.util.List;
 
 public class DBRefEntry implements DBRefEntryI
 {
-  /*
-   * the mapping to chromosome (genome) is held as an instance with
-   * source = speciesId
-   * version = assemblyId
-   * accessionId = "chromosome:" + chromosomeId
-   * map = mapping from sequence to reference assembly
-   */
-  public static final String CHROMOSOME = "chromosome";
-
   String source = "";
 
   String version = "";
@@ -344,14 +335,4 @@ public class DBRefEntry implements DBRefEntryI
     }
     return true;
   }
-
-  /**
-   * Mappings to chromosome are held with accessionId as "chromosome:id"
-   * 
-   * @return
-   */
-  public boolean isChromosome()
-  {
-    return accessionId != null && accessionId.startsWith(CHROMOSOME + ":");
-  }
 }
index f8c7ec5..09db9d7 100644 (file)
@@ -34,5 +34,5 @@ public interface GeneLociI
    * 
    * @return
    */
-  MapList getMap();
+  MapList getMapping();
 }
diff --git a/src/jalview/datamodel/GeneLocus.java b/src/jalview/datamodel/GeneLocus.java
new file mode 100644 (file)
index 0000000..f81348f
--- /dev/null
@@ -0,0 +1,91 @@
+package jalview.datamodel;
+
+import jalview.util.MapList;
+
+/**
+ * A specialisation of DBRefEntry used to hold the chromosomal coordinates for a
+ * (typically gene) sequence
+ * <ul>
+ * <li>field <code>source</code> is used to hold a species id e.g. human</li>
+ * <li>field <code>version</code> is used to hold assembly id e.g GRCh38</li>
+ * <li>field <code>accession</code> is used to hold the chromosome id</li>
+ * <li>field <code>map</code> is used to hold the mapping from sequence to
+ * chromosome coordinates</li>
+ * </ul>
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class GeneLocus extends DBRefEntry implements GeneLociI
+{
+  /**
+   * Constructor adapts species, assembly, chromosome to DBRefEntry source,
+   * version, accession, respectively, and saves the mapping of sequence to
+   * chromosomal coordinates
+   * 
+   * @param speciesId
+   * @param assemblyId
+   * @param chromosomeId
+   * @param mapping
+   */
+  public GeneLocus(String speciesId, String assemblyId, String chromosomeId,
+          Mapping mapping)
+  {
+    super(speciesId, assemblyId, chromosomeId, mapping);
+  }
+
+  /**
+   * Constructor
+   * 
+   * @param speciesId
+   * @param assemblyId
+   * @param chromosomeId
+   */
+  public GeneLocus(String speciesId, String assemblyId, String chromosomeId)
+  {
+    this(speciesId, assemblyId, chromosomeId, null);
+  }
+
+  @Override
+  public boolean equals(Object o)
+  {
+    return o instanceof GeneLocus && super.equals(o);
+  }
+
+  @Override
+  public MapList getMapping()
+  {
+    return map == null ? null : map.getMap();
+  }
+
+  /**
+   * Answers the species identifier e.g. "human", stored as field <code>source</code> of
+   * DBRefEntry
+   */
+  @Override
+  public String getSpeciesId()
+  {
+    return getSource();
+  }
+
+  /**
+   * Answers the genome assembly id e.g. "GRCh38", stored as field
+   * <code>version</code> of DBRefEntry
+   */
+  @Override
+  public String getAssemblyId()
+  {
+    return getVersion();
+  }
+
+  /**
+   * Answers the chromosome identifier e.g. "X", stored as field
+   * <code>accession</code> of DBRefEntry
+   */
+  @Override
+  public String getChromosomeId()
+  {
+    return getAccessionId();
+  }
+
+}
index 80310c0..6f5c18a 100755 (executable)
@@ -670,8 +670,8 @@ public class Sequence extends ASequence implements SequenceI
   public void setGeneLoci(String speciesId, String assemblyId,
           String chromosomeId, MapList map)
   {
-    addDBRef(new DBRefEntry(speciesId, assemblyId, DBRefEntry.CHROMOSOME
-            + ":" + chromosomeId, new Mapping(map)));
+    addDBRef(new GeneLocus(speciesId, assemblyId, chromosomeId,
+            new Mapping(map)));
   }
 
   /**
@@ -687,36 +687,9 @@ public class Sequence extends ASequence implements SequenceI
     {
       for (final DBRefEntry ref : refs)
       {
-        if (ref.isChromosome())
+        if (ref instanceof GeneLociI)
         {
-          return new GeneLociI()
-          {
-            @Override
-            public String getSpeciesId()
-            {
-              return ref.getSource();
-            }
-
-            @Override
-            public String getAssemblyId()
-            {
-              return ref.getVersion();
-            }
-
-            @Override
-            public String getChromosomeId()
-            {
-              // strip off "chromosome:" prefix to chrId
-              return ref.getAccessionId().substring(
-                      DBRefEntry.CHROMOSOME.length() + 1);
-            }
-
-            @Override
-            public MapList getMap()
-            {
-              return ref.getMap().getMap();
-            }
-          };
+          return (GeneLociI) ref;
         }
       }
     }
index 744191d..99ebc69 100644 (file)
@@ -130,6 +130,7 @@ class EnsemblFeatures extends EnsemblRestClient
           int end = Integer.parseInt(obj.get("end").toString());
           String source = obj.get("source").toString();
           String strand = obj.get("strand").toString();
+          Object phase = obj.get("phase");
           String alleles = JSONUtils
                   .arrayToList((JSONArray) obj.get("alleles"));
           String clinSig = JSONUtils
@@ -155,6 +156,10 @@ class EnsemblFeatures extends EnsemblRestClient
           SequenceFeature sf = new SequenceFeature(type, desc, start, end,
                   source);
           sf.setStrand("1".equals(strand) ? "+" : "-");
+          if (phase != null)
+          {
+            sf.setPhase(phase.toString());
+          }
           setFeatureAttribute(sf, obj, "id");
           setFeatureAttribute(sf, obj, "Parent");
           setFeatureAttribute(sf, obj, "consequence_type");
index 7648536..9c7ce63 100644 (file)
@@ -23,7 +23,6 @@ package jalview.ext.ensembl;
 import jalview.api.FeatureColourI;
 import jalview.api.FeatureSettingsModelI;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.GeneLociI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
@@ -62,6 +61,8 @@ public class EnsemblGene extends EnsemblSeqProxy
       EnsemblFeatureType.exon, EnsemblFeatureType.cds,
       EnsemblFeatureType.variation };
 
+  private static final String CHROMOSOME = "chromosome";
+
   /**
    * Default constructor (to use rest.ensembl.org)
    */
@@ -187,7 +188,7 @@ public class EnsemblGene extends EnsemblSeqProxy
     if (geneLoci != null)
     {
       seq.setGeneLoci(geneLoci.getSpeciesId(), geneLoci.getAssemblyId(),
-              geneLoci.getChromosomeId(), geneLoci.getMap());
+              geneLoci.getChromosomeId(), geneLoci.getMapping());
     }
     else
     {
@@ -209,7 +210,7 @@ public class EnsemblGene extends EnsemblSeqProxy
       return false;
     }
     String[] tokens = description.split(":");
-    if (tokens.length == 6 && tokens[0].startsWith(DBRefEntry.CHROMOSOME))
+    if (tokens.length == 6 && tokens[0].startsWith(CHROMOSOME))
     {
       String ref = tokens[1];
       String chrom = tokens[2];
@@ -460,7 +461,7 @@ public class EnsemblGene extends EnsemblSeqProxy
       return;
     }
 
-    MapList geneMapping = loci.getMap();
+    MapList geneMapping = loci.getMapping();
 
     List<int[]> exons = mapping.getFromRanges();
     List<int[]> transcriptLoci = new ArrayList<>();
index c6b794a..b412849 100644 (file)
@@ -23,6 +23,8 @@ package jalview.ext.ensembl;
 import jalview.bin.Cache;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.GeneLociI;
+import jalview.datamodel.GeneLocus;
+import jalview.datamodel.Mapping;
 import jalview.util.MapList;
 
 import java.io.BufferedReader;
@@ -287,34 +289,10 @@ public class EnsemblLookup extends EnsemblRestClient
           fromEnd });
       List<int[]> toRange = Collections.singletonList(new int[] { toStart,
           toEnd });
-      final MapList map = new MapList(fromRange, toRange, 1, 1);
-      return new GeneLociI()
-      {
-
-        @Override
-        public String getSpeciesId()
-        {
-          return species == null ? "" : species;
-        }
-
-        @Override
-        public String getAssemblyId()
-        {
-          return assembly;
-        }
-
-        @Override
-        public String getChromosomeId()
-        {
-          return chromosome;
-        }
-
-        @Override
-        public MapList getMap()
-        {
-          return map;
-        }
-      };
+      final Mapping map = new Mapping(
+              new MapList(fromRange, toRange, 1, 1));
+      return new GeneLocus(species == null ? "" : species, assembly,
+              chromosome, map);
     } catch (NullPointerException | NumberFormatException e)
     {
       Cache.log.error("Error looking up gene loci: " + e.getMessage());
index b1c9d86..c688a6f 100644 (file)
@@ -3,6 +3,8 @@ package jalview.ext.ensembl;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefSource;
 import jalview.datamodel.GeneLociI;
+import jalview.datamodel.GeneLocus;
+import jalview.datamodel.Mapping;
 import jalview.util.MapList;
 
 import java.io.BufferedReader;
@@ -386,34 +388,9 @@ public class EnsemblMap extends EnsemblRestClient
       final String chr = chromosome;
       List<int[]> fromRange = Collections.singletonList(new int[] { 1,
           fromEnd });
-      final MapList map = new MapList(fromRange, regions, 1, 1);
-      return new GeneLociI()
-      {
-
-        @Override
-        public String getSpeciesId()
-        {
-          return species == null ? "" : species;
-        }
-
-        @Override
-        public String getAssemblyId()
-        {
-          return as;
-        }
-
-        @Override
-        public String getChromosomeId()
-        {
-          return chr;
-        }
-
-        @Override
-        public MapList getMap()
-        {
-          return map;
-        }
-      };
+      Mapping mapping = new Mapping(new MapList(fromRange, regions, 1, 1));
+      return new GeneLocus(species == null ? "" : species, as, chr,
+              mapping);
     } catch (IOException | ParseException | NumberFormatException e)
     {
       // ignore
index 04525f0..2859e0f 100644 (file)
@@ -1,5 +1,7 @@
 package jalview.ext.htsjdk;
 
+import jalview.bin.Cache;
+
 import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
@@ -19,36 +21,52 @@ public class VCFReader implements Closeable, Iterable<VariantContext>
 
   private static final String TBI_EXTENSION = ".tbi";
 
+  private static final String CSI_EXTENSION = ".csi";
+
   private boolean indexed;
 
   private VCFFileReader reader;
 
   /**
-   * Constructor given a raw or compressed VCF file or a (tabix) index file
+   * Constructor given a raw or compressed VCF file or a (csi or tabix) index file
    * <p>
-   * For now, file type is inferred from its suffix: .gz or .bgz for compressed
-   * data, .tbi for an index file, anything else is assumed to be plain text
-   * VCF.
+   * If the file path ends in ".tbi" or ".csi", <em>or</em> appending one of these
+   * extensions gives a valid file path, open as indexed, else as unindexed.
    * 
    * @param f
    * @throws IOException
    */
   public VCFReader(String filePath) throws IOException
   {
-    if (filePath.endsWith(GZ))
+    indexed = false;
+    if (filePath.endsWith(TBI_EXTENSION)
+            || filePath.endsWith(CSI_EXTENSION))
     {
-      if (new File(filePath + TBI_EXTENSION).exists())
-      {
-        indexed = true;
-      }
+      indexed = true;
+      filePath = filePath.substring(0, filePath.length() - 4);
     }
-    else if (filePath.endsWith(TBI_EXTENSION))
+    else if (new File(filePath + TBI_EXTENSION).exists())
+    {
+      indexed = true;
+    }
+    else if (new File(filePath + CSI_EXTENSION).exists())
     {
       indexed = true;
-      filePath = filePath.substring(0, filePath.length() - 4);
     }
 
-    reader = new VCFFileReader(new File(filePath), indexed);
+    /*
+     * we pass the name of the unindexed file to htsjdk,
+     * with a flag to assert whether it is indexed
+     */
+    File file = new File(filePath);
+    if (file.exists())
+    {
+      reader = new VCFFileReader(file, indexed);
+    }
+    else
+    {
+      Cache.log.error("File not found: " + filePath);
+    }
   }
 
   @Override
@@ -88,9 +106,10 @@ public class VCFReader implements Closeable, Iterable<VariantContext>
   public CloseableIterator<VariantContext> query(final String chrom,
           final int start, final int end)
   {
-   if (reader == null) {
-     return null;
-   }
+    if (reader == null)
+    {
+      return null;
+    }
     if (indexed)
     {
       return reader.query(chrom, start, end);
@@ -116,7 +135,7 @@ public class VCFReader implements Closeable, Iterable<VariantContext>
   {
     final CloseableIterator<VariantContext> it = reader.iterator();
     
-    return new CloseableIterator()
+    return new CloseableIterator<VariantContext>()
     {
       boolean atEnd = false;
 
index 31f7a6d..05f5e08 100644 (file)
@@ -86,7 +86,8 @@ public class APQHandlers
                         QuitEvent e, QuitResponse r)
                 {
                   boolean confirmQuit = jalview.bin.Cache
-                          .getDefault(jalviewDesktop.CONFIRM_KEYBOARD_QUIT,
+                          .getDefault(
+                                  jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT,
                                   true);
                   int n;
                   if (confirmQuit)
@@ -134,12 +135,12 @@ public class APQHandlers
       {
         System.out.println(
                 "Exception when looking for About, Preferences, Quit Handlers");
-        e.printStackTrace();
+        // e.printStackTrace();
       } catch (Throwable t)
       {
         System.out.println(
                 "Throwable when looking for About, Preferences, Quit Handlers");
-        t.printStackTrace();
+        // t.printStackTrace();
       }
 
     }
index 0ab7515..f3a8ab5 100644 (file)
@@ -1203,23 +1203,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           PrintWriter out = new PrintWriter(
                   new FileWriter(backupfiles.getTempFilePath()));
 
-          // TESTING code here
-          boolean TESTING = true;
-          if (TESTING)
-          {
-            out.print("; TESTSTART\n");
-            int count = 20;
-            for (int i = 0; i < count; i++)
-            {
-              // Thread.sleep(1000);
-              out.println("; TEST: " + (count - 1 - i));
-            }
-          }
           out.print(output);
-          if (TESTING)
-          {
-            out.print("; TESTEND\n");
-          }
           out.close();
           this.setTitle(file);
           statusBar.setText(MessageManager.formatMessage(
index 85f2498..51ac2ee 100644 (file)
@@ -356,12 +356,12 @@ public class CrossRefAction implements Runnable
             seq.getLength());
     if (geneLoci != null)
     {
-      MapList map = geneLoci.getMap();
+      MapList map = geneLoci.getMapping();
       int mappedFromLength = MappingUtils.getLength(map.getFromRanges());
       if (mappedFromLength == seq.getLength())
       {
         seq.setGeneLoci(geneLoci.getSpeciesId(), geneLoci.getAssemblyId(),
-                geneLoci.getChromosomeId(), geneLoci.getMap());
+                geneLoci.getChromosomeId(), map);
         retrievedLoci.put(dbref, geneLoci);
         return true;
       }
@@ -374,12 +374,12 @@ public class CrossRefAction implements Runnable
             seq.getLength());
     if (geneLoci != null)
     {
-      MapList map = geneLoci.getMap();
+      MapList map = geneLoci.getMapping();
       int mappedFromLength = MappingUtils.getLength(map.getFromRanges());
       if (mappedFromLength == seq.getLength())
       {
         seq.setGeneLoci(geneLoci.getSpeciesId(), geneLoci.getAssemblyId(),
-                geneLoci.getChromosomeId(), geneLoci.getMap());
+                geneLoci.getChromosomeId(), map);
         retrievedLoci.put(dbref, geneLoci);
         return true;
       }
index 41cbad8..0523d41 100644 (file)
@@ -366,12 +366,12 @@ public class Desktop extends jalview.jbgui.GDesktop
       APQHandlers.setAPQHandlers(this);
     } catch (Exception e)
     {
-      System.out.println("Exception when trying to set APQHandlers");
-      e.printStackTrace();
+      System.out.println("Cannot set APQHandlers");
+      // e.printStackTrace();
     } catch (Throwable t)
     {
-      System.out.println("Throwable when trying to set APQHandlers");
-      t.printStackTrace();
+      System.out.println("Cannot set APQHandlers");
+      // t.printStackTrace();
     }
 
 
@@ -1134,7 +1134,7 @@ public class Desktop extends jalview.jbgui.GDesktop
   {
     String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT");
     JalviewFileChooser chooser = JalviewFileChooser
-            .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat, true);
+            .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat, BackupFiles.getEnabled());
 
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(
@@ -1299,8 +1299,6 @@ public class Desktop extends jalview.jbgui.GDesktop
   @Override
   public void quit()
   {
-    //System.out.println("********** Desktop.quit()");
-    //System.out.println(savingFiles.toString());
     Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
     jalview.bin.Cache.setProperty("SCREENGEOMETRY_WIDTH",
             screen.width + "");
@@ -1763,7 +1761,7 @@ public class Desktop extends jalview.jbgui.GDesktop
         "Jalview Project (old)" };
     JalviewFileChooser chooser = new JalviewFileChooser(
             Cache.getProperty("LAST_DIRECTORY"), suffix, desc,
-            "Jalview Project", true, true); // last two booleans: allFiles,
+            "Jalview Project", true, BackupFiles.getEnabled()); // last two booleans: allFiles,
                                             // allowBackupFiles
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(MessageManager.getString("label.restore_state"));
index a2194f4..7456e18 100644 (file)
@@ -22,6 +22,7 @@ package jalview.gui;
 
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureColourI;
+import jalview.bin.Cache;
 import jalview.datamodel.GraphLine;
 import jalview.datamodel.features.FeatureAttributes;
 import jalview.datamodel.features.FeatureAttributes.Datatype;
@@ -165,7 +166,7 @@ public class FeatureTypeSettings extends JalviewDialog
 
   private JPanel maxColour = new JPanel();
 
-  private JComboBox<String> threshold = new JComboBox<>();
+  private JComboBox<Object> threshold = new JComboBox<>();
 
   private JSlider slider = new JSlider();
 
@@ -182,17 +183,17 @@ public class FeatureTypeSettings extends JalviewDialog
   /*
    * choice of option for 'colour for no value'
    */
-  private JComboBox<String> noValueCombo;
+  private JComboBox<Object> noValueCombo;
 
   /*
    * choice of what to colour by text (Label or attribute)
    */
-  private JComboBox<String> colourByTextCombo;
+  private JComboBox<Object> colourByTextCombo;
 
   /*
    * choice of what to colour by range (Score or attribute)
    */
-  private JComboBox<String> colourByRangeCombo;
+  private JComboBox<Object> colourByRangeCombo;
 
   private JRadioButton andFilters;
 
@@ -1104,7 +1105,7 @@ public class FeatureTypeSettings extends JalviewDialog
    * @param withRange
    * @param withText
    */
-  protected JComboBox<String> populateAttributesDropdown(
+  protected JComboBox<Object> populateAttributesDropdown(
           List<String[]> attNames, boolean withRange, boolean withText)
   {
     List<String> displayAtts = new ArrayList<>();
@@ -1143,9 +1144,11 @@ public class FeatureTypeSettings extends JalviewDialog
       tooltips.add(desc == null ? "" : desc);
     }
 
-    JComboBox<String> attCombo = JvSwingUtils
-            .buildComboWithTooltips(displayAtts, tooltips);
-
+    // now convert String List to Object List for buildComboWithTooltips
+    List<Object> displayAttsObjects = new ArrayList<>(displayAtts);
+    JComboBox<Object> attCombo = JvSwingUtils
+            .buildComboWithTooltips(displayAttsObjects, tooltips);
+    
     return attCombo;
   }
 
@@ -1316,7 +1319,7 @@ public class FeatureTypeSettings extends JalviewDialog
      * drop-down choice of attribute, with description as a tooltip 
      * if we can obtain it
      */
-    final JComboBox<String> attCombo = populateAttributesDropdown(attNames,
+    final JComboBox<Object> attCombo = populateAttributesDropdown(attNames,
             true, true);
     String filterBy = setSelectedAttribute(attCombo, filter);
 
@@ -1444,7 +1447,7 @@ public class FeatureTypeSettings extends JalviewDialog
    * @param attCombo
    * @param filter
    */
-  private String setSelectedAttribute(JComboBox<String> attCombo,
+  private String setSelectedAttribute(JComboBox<Object> attCombo,
           FeatureMatcherI filter)
   {
     String item = null;
@@ -1661,11 +1664,19 @@ public class FeatureTypeSettings extends JalviewDialog
    * @param valueField
    * @param filterIndex
    */
-  protected boolean updateFilter(JComboBox<String> attCombo,
+  protected boolean updateFilter(JComboBox<Object> attCombo,
           JComboBox<Condition> condCombo, JTextField valueField,
           int filterIndex)
   {
-    String attName = (String) attCombo.getSelectedItem();
+    String attName;
+    try
+    {
+      attName = (String) attCombo.getSelectedItem();
+    } catch (Exception e)
+    {
+      Cache.log.error("Problem casting Combo box entry to String");
+      attName = attCombo.getSelectedItem().toString();
+    }
     Condition cond = (Condition) condCombo.getSelectedItem();
     String pattern = valueField.getText().trim();
 
index 4658668..d6090e2 100644 (file)
@@ -319,13 +319,13 @@ public final class JvSwingUtils
    * @param entries
    * @param tooltips
    */
-  public static JComboBox<String> buildComboWithTooltips(
-          List<String> entries, List<String> tooltips)
+  public static JComboBox<Object> buildComboWithTooltips(
+          List<Object> entries, List<String> tooltips)
   {
-    JComboBox<String> combo = new JComboBox<>();
+    JComboBox<Object> combo = new JComboBox<>();
     final ComboBoxTooltipRenderer renderer = new ComboBoxTooltipRenderer();
     combo.setRenderer(renderer);
-    for (String attName : entries)
+    for (Object attName : entries)
     {
       combo.addItem(attName);
     }
index ab09f74..9754e0d 100755 (executable)
@@ -25,6 +25,7 @@ import jalview.bin.Cache;
 import jalview.gui.Help.HelpId;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.BackupFiles;
+import jalview.io.BackupFilesPresetEntry;
 import jalview.io.FileFormatI;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
@@ -805,22 +806,25 @@ public class Preferences extends GPreferences
     /*
      * Save Backups settings
      */
-    Cache.applicationProperties.setProperty(BackupFiles.CONFIRM_DELETE_OLD,
-            Boolean.toString(backupfilesConfirmDelete.isSelected()));
     Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
             Boolean.toString(enableBackupFiles.isSelected()));
-    Cache.applicationProperties.setProperty(BackupFiles.NO_MAX,
-            Boolean.toString(backupfilesKeepAll.isSelected()));
-    Cache.applicationProperties.setProperty(BackupFiles.REVERSE_ORDER,
-            Boolean.toString(suffixReverse.isSelected()));
-    Cache.applicationProperties.setProperty(BackupFiles.SUFFIX,
-            suffixTemplate.getText());
-    Cache.applicationProperties.setProperty(BackupFiles.ROLL_MAX,
-            Integer.toString(getSpinnerInt(backupfilesRollMaxSpinner, 4)));
-    Cache.applicationProperties.setProperty(BackupFiles.SUFFIX_DIGITS,
-            Integer.toString(getSpinnerInt(suffixDigitsSpinner, 3)));
-    Cache.applicationProperties.setProperty(BackupFiles.NS+"_PRESET",
-            Integer.toString(getComboIntStringKey(backupfilesPresetsCombo)));
+    int preset = getComboIntStringKey(backupfilesPresetsCombo);
+    Cache.applicationProperties.setProperty(BackupFiles.NS + "_PRESET", Integer.toString(preset));
+
+    if (preset == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
+    {
+      BackupFilesPresetEntry customBFPE = getBackupfilesCurrentEntry();
+      BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
+              BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM, customBFPE);
+      Cache.applicationProperties
+              .setProperty(BackupFilesPresetEntry.CUSTOMCONFIG,
+                      customBFPE.toString());
+    }
+
+    BackupFilesPresetEntry savedBFPE = BackupFilesPresetEntry.backupfilesPresetEntriesValues
+            .get(preset);
+    Cache.applicationProperties.setProperty(
+            BackupFilesPresetEntry.SAVEDCONFIG, savedBFPE.toString());
 
     Cache.saveProperties();
     Desktop.instance.doConfigureStructurePrefs();
index 4a4c10c..25dedc5 100644 (file)
@@ -29,7 +29,6 @@ import jalview.util.Platform;
 import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Component;
-import java.awt.Toolkit;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
@@ -43,6 +42,8 @@ import java.util.Map.Entry;
 import javax.swing.AbstractAction;
 import javax.swing.InputMap;
 import javax.swing.JComponent;
+import javax.swing.JDesktopPane;
+import javax.swing.JInternalFrame;
 import javax.swing.JMenuItem;
 import javax.swing.KeyStroke;
 import javax.swing.event.InternalFrameAdapter;
@@ -789,4 +790,29 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
     };
     overrideKeyBinding(key_cmdF, action);
   }
+
+  /**
+   * Override to do nothing if triggered from one of the child frames
+   */
+  @Override
+  public void setSelected(boolean selected) throws PropertyVetoException
+  {
+    JDesktopPane desktopPane = getDesktopPane();
+    JInternalFrame fr = desktopPane == null ? null
+            : desktopPane.getSelectedFrame();
+    if (fr == getTopFrame() || fr == getBottomFrame())
+    {
+      /* 
+       * patch for JAL-3288 (deselecting top/bottom frame closes popup menu); 
+       * it may be possible to remove this method in future
+       * if the underlying Java behaviour changes
+       */
+      if (selected)
+      {
+        moveToFront();
+      }
+      return;
+    }
+    super.setSelected(selected);
+  }
 }
index 4f93ece..1504404 100644 (file)
@@ -1,7 +1,5 @@
 package jalview.io;
 
-import jalview.bin.Cache;
-
 import java.io.File;
 
 public class BackupFilenameParts
@@ -113,7 +111,9 @@ public class BackupFilenameParts
           String filename, String base, boolean extensionMatch)
   {
     BackupFilenameParts bfp = new BackupFilenameParts();
-    String template = Cache.getDefault(BackupFiles.SUFFIX, null);
+    BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
+            .getSavedBackupEntry();
+    String template = bfpe.suffix;
     if (template == null)
     {
       return bfp;
@@ -121,8 +121,7 @@ public class BackupFilenameParts
     int digits;
     try
     {
-      digits = Integer
-              .parseInt(Cache.getDefault(BackupFiles.SUFFIX_DIGITS, null));
+      digits = bfpe.digits;
     } catch (Exception e)
     {
       return bfp;
index dbda022..7bb5d31 100644 (file)
@@ -17,12 +17,8 @@ import java.util.TreeMap;
  * BackupFiles used for manipulating (naming rolling/deleting) backup/version files when an alignment or project file is saved.
  * User configurable options are:
  * BACKUPFILES_ENABLED - boolean flag as to whether to use this mechanism or act as before, including overwriting files as saved.
- * BACKUPFILES_SUFFIX - a template to insert after the file extension.  Use '%n' to be replaced by a 0-led SUFFIX_DIGITS long integer.
- * BACKUPFILES_NO_MAX - flag to turn off setting a maximum number of backup files to keep.
- * BACKUPFILES_ROLL_MAX - the maximum number of backupfiles to keep for any one alignment or project file.
- * BACKUPFILES_SUFFIX_DIGITS - the number of digits to insert replace %n with (e.g. BACKUPFILES_SUFFIX_DIGITS = 3 would make "001", "002", etc)
- * BACKUPFILES_REVERSE_ORDER - if true then "logfile" style numbering and file rolling will occur. If false then ever-increasing version numbering will occur, but old files will still be deleted if there are more than ROLL_MAX backup files. 
- * BACKUPFILES_CONFIRM_DELETE_OLD - if true then prompt/confirm with the user when deleting older backup/version files.
+ * The rest of the options are now saved as BACKUPFILES_PRESET, BACKUPFILES_SAVED and BACKUPFILES_CUSTOM
+ * (see BackupFilesPresetEntry)
  */
 
 public class BackupFiles
@@ -33,21 +29,8 @@ public class BackupFiles
 
   public static final String ENABLED = NS + "_ENABLED";
 
-  public static final String SUFFIX = NS + "_SUFFIX";
-
-  public static final String NO_MAX = NS + "_NO_MAX";
-
-  public static final String ROLL_MAX = NS + "_ROLL_MAX";
-
-  public static final String SUFFIX_DIGITS = NS + "_SUFFIX_DIGITS";
-
   public static final String NUM_PLACEHOLDER = "%n";
 
-  public static final String REVERSE_ORDER = NS + "_REVERSE_ORDER";
-
-  public static final String CONFIRM_DELETE_OLD = NS
-          + "_CONFIRM_DELETE_OLD";
-
   private static final String DEFAULT_TEMP_FILE = "jalview_temp_file_" + NS;
 
   private static final String TEMP_FILE_EXT = ".tmp";
@@ -101,20 +84,14 @@ public class BackupFiles
   // REVERSE_ORDER
   public BackupFiles(File file)
   {
-    this(file, ".bak" + NUM_PLACEHOLDER, false, 3, 3, false);
-  }
-
-  public BackupFiles(File file, String defaultSuffix, boolean defaultNoMax,
-          int defaultMax, int defaultDigits, boolean defaultReverseOrder)
-  {
     classInit();
     this.file = file;
-    this.suffix = Cache.getDefault(SUFFIX, defaultSuffix);
-    this.noMax = Cache.getDefault(NO_MAX, defaultNoMax);
-    this.max = Cache.getDefault(ROLL_MAX, defaultMax);
-    this.digits = Cache.getDefault(SUFFIX_DIGITS, defaultDigits);
-    this.reverseOrder = Cache.getDefault(REVERSE_ORDER,
-            defaultReverseOrder);
+    BackupFilesPresetEntry bfpe = BackupFilesPresetEntry.getSavedBackupEntry();
+    this.suffix = bfpe.suffix;
+    this.noMax = bfpe.keepAll;
+    this.max = bfpe.rollMax;
+    this.digits = bfpe.digits;
+    this.reverseOrder = bfpe.reverse;
 
     // create a temp file to save new data in
     File temp = null;
@@ -145,7 +122,9 @@ public class BackupFiles
   public static void classInit()
   {
     setEnabled(Cache.getDefault(ENABLED, true));
-    setConfirmDelete(Cache.getDefault(CONFIRM_DELETE_OLD, true));
+    BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
+            .getSavedBackupEntry();
+    setConfirmDelete(bfpe.confirmDelete);
   }
 
   public static void setEnabled(boolean flag)
diff --git a/src/jalview/io/BackupFilesPresetEntry.java b/src/jalview/io/BackupFilesPresetEntry.java
new file mode 100644 (file)
index 0000000..4face29
--- /dev/null
@@ -0,0 +1,173 @@
+package jalview.io;
+
+import jalview.bin.Cache;
+import jalview.util.MessageManager;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+public class BackupFilesPresetEntry
+{
+
+  public String suffix;
+
+  public static final int DIGITSMIN = 1;
+
+  public static final int DIGITSMAX = 6;
+
+  public int digits;
+
+  public boolean reverse;
+
+  public boolean keepAll;
+
+  public static final int ROLLMAXMIN = 1;
+
+  public static final int ROLLMAXMAX = 999;
+
+  public int rollMax;
+
+  public boolean confirmDelete;
+
+  public static final String SAVEDCONFIG = BackupFiles.NS + "_SAVED";
+
+  public static final String CUSTOMCONFIG = BackupFiles.NS + "_CUSTOM";
+
+  private static final String stringDelim = "\t";
+
+  public static final int BACKUPFILESSCHEMECUSTOM = 0;
+
+  public static final int BACKUPFILESSCHEMEDEFAULT = 1;
+
+  public BackupFilesPresetEntry(String suffix, int digits, boolean reverse,
+          boolean keepAll, int rollMax, boolean confirmDelete)
+  {
+    this.suffix = suffix == null ? "" : suffix;
+    this.digits = digits < DIGITSMIN ? DIGITSMIN
+            : (digits > DIGITSMAX ? DIGITSMAX : digits);
+    this.reverse = reverse;
+    this.keepAll = keepAll;
+    this.rollMax = rollMax < ROLLMAXMIN ? ROLLMAXMIN
+            : (rollMax > ROLLMAXMAX ? ROLLMAXMAX : rollMax);
+    this.confirmDelete = confirmDelete;
+  }
+
+  public boolean equals(BackupFilesPresetEntry compare)
+  {
+    return suffix.equals(compare.suffix) && digits == compare.digits
+            && reverse == compare.reverse && keepAll == compare.keepAll
+            && rollMax == compare.rollMax
+            && confirmDelete == compare.confirmDelete;
+  }
+
+  @Override
+  public String toString()
+  {
+    StringBuilder sb = new StringBuilder();
+    sb.append(suffix);
+    sb.append(stringDelim);
+    sb.append(digits);
+    sb.append(stringDelim);
+    sb.append(reverse);
+    sb.append(stringDelim);
+    sb.append(keepAll);
+    sb.append(stringDelim);
+    sb.append(rollMax);
+    sb.append(stringDelim);
+    sb.append(confirmDelete);
+    return sb.toString();
+  }
+
+  public static BackupFilesPresetEntry createBackupFilesPresetEntry(
+          String line)
+  {
+    if (line == null)
+    {
+      return null;
+    }
+    StringTokenizer st = new StringTokenizer(line, stringDelim);
+    String suffix = null;
+    int digits = 0;
+    boolean reverse = false;
+    boolean keepAll = false;
+    int rollMax = 0;
+    boolean confirmDelete = false;
+
+    try
+    {
+      suffix = st.nextToken();
+      digits = Integer.valueOf(st.nextToken());
+      reverse = Boolean.valueOf(st.nextToken());
+      keepAll = Boolean.valueOf(st.nextToken());
+      rollMax = Integer.valueOf(st.nextToken());
+      confirmDelete = Boolean.valueOf(st.nextToken());
+    } catch (Exception e)
+    {
+      Cache.log.error("Error parsing backupfiles scheme '" + line + "'");
+    }
+
+    return new BackupFilesPresetEntry(suffix, digits, reverse, keepAll,
+            rollMax, confirmDelete);
+  }
+
+  public static BackupFilesPresetEntry getSavedBackupEntry()
+  {
+    String savedPresetString = Cache
+            .getDefault(BackupFilesPresetEntry.SAVEDCONFIG, null);
+    BackupFilesPresetEntry savedPreset = BackupFilesPresetEntry
+            .createBackupFilesPresetEntry(savedPresetString);
+    if (savedPreset == null)
+    {
+      savedPreset = backupfilesPresetEntriesValues
+              .get(BACKUPFILESSCHEMEDEFAULT);
+    }
+    return savedPreset;
+  }
+
+  public static final IntKeyStringValueEntry[] backupfilesPresetEntries = {
+      new IntKeyStringValueEntry(BACKUPFILESSCHEMEDEFAULT,
+              MessageManager.getString("label.default")),
+      new IntKeyStringValueEntry(2,
+              MessageManager.getString("label.single_file")),
+      new IntKeyStringValueEntry(3,
+              MessageManager.getString("label.keep_all_versions")),
+      new IntKeyStringValueEntry(4,
+              MessageManager.getString("label.rolled_backups")),
+      // ...
+      // IMPORTANT, keep "Custom" entry with key 0 (even though it appears last)
+      new IntKeyStringValueEntry(BACKUPFILESSCHEMECUSTOM,
+              MessageManager.getString("label.custom")) };
+
+  public static final String[] backupfilesPresetEntryDescriptions = {
+      MessageManager.getString("label.default_description"),
+      MessageManager.getString("label.single_file_description"),
+      MessageManager.getString("label.keep_all_versions_description"),
+      MessageManager.getString("label.rolled_backups_description"),
+      MessageManager.getString("label.custom_description") };
+
+  public static final Map<Integer, BackupFilesPresetEntry> backupfilesPresetEntriesValues = new HashMap<Integer, BackupFilesPresetEntry>()
+  {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 125L;
+
+    {
+      put(1, new BackupFilesPresetEntry(
+              ".bak" + BackupFiles.NUM_PLACEHOLDER, 3, false, false, 3,
+              false));
+      put(2, new BackupFilesPresetEntry("~", 1, false, false, 1, false));
+      put(3, new BackupFilesPresetEntry(".v" + BackupFiles.NUM_PLACEHOLDER,
+              3, false, true, 10, true));
+      put(4, new BackupFilesPresetEntry(
+              "_bak." + BackupFiles.NUM_PLACEHOLDER, 1, true, false, 9,
+              false));
+
+      // This gets replaced by GPreferences
+      put(BACKUPFILESSCHEMECUSTOM,
+              new BackupFilesPresetEntry("", 0, false, false, 0, false));
+    }
+  };
+
+}
diff --git a/src/jalview/io/IntKeyStringValueEntry.java b/src/jalview/io/IntKeyStringValueEntry.java
new file mode 100644 (file)
index 0000000..084dbc5
--- /dev/null
@@ -0,0 +1,21 @@
+package jalview.io;
+
+public class IntKeyStringValueEntry
+{
+  public final int k;
+
+  public final String v;
+
+  public IntKeyStringValueEntry(int k, String v)
+  {
+    this.k = k;
+    this.v = v;
+  }
+
+  @Override
+  public String toString()
+  {
+    return v;
+  }
+
+}
index 6b82671..dd09d03 100644 (file)
@@ -23,6 +23,7 @@ package jalview.io;
 import jalview.api.FeatureColourI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
+import jalview.datamodel.GeneLociI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.util.MessageManager;
@@ -68,11 +69,11 @@ public class SequenceAnnotationReport
     @Override
     public int compare(DBRefEntry ref1, DBRefEntry ref2)
     {
-      if (ref1.isChromosome())
+      if (ref1 instanceof GeneLociI)
       {
         return -1;
       }
-      if (ref2.isChromosome())
+      if (ref2 instanceof GeneLociI)
       {
         return 1;
       }
index 72e906c..7d354e0 100644 (file)
@@ -70,6 +70,7 @@ public class SequenceOntologyLite implements SequenceOntologyI
     { "snRNA", "transcript" },
     { "miRNA", "transcript" },
     { "lincRNA", "transcript" },
+    { "lnc_RNA", "transcript" },
     { "rRNA", "transcript" },
     { "mRNA", "transcript" },
     // there are many more sub-types of ncRNA...
index 9831af7..7bf7791 100644 (file)
@@ -100,10 +100,12 @@ public class VCFLoader
    */
   private static final String VCF_ASSEMBLY = "VCF_ASSEMBLY";
 
-  private static final String DEFAULT_VCF_ASSEMBLY = "assembly19=GRCh38,hs37=GRCh37,grch37=GRCh37,grch38=GRCh38";
+  private static final String DEFAULT_VCF_ASSEMBLY = "assembly19=GRCh37,hs37=GRCh37,grch37=GRCh37,grch38=GRCh38";
 
   private static final String VCF_SPECIES = "VCF_SPECIES"; // default is human
 
+  private static final String DEFAULT_REFERENCE = "grch37"; // fallback default is human GRCh37
+
   /*
    * keys to fields of VEP CSQ consequence data
    * see https://www.ensembl.org/info/docs/tools/vep/vep_formats.html
@@ -263,7 +265,12 @@ public class VCFLoader
   public SequenceI loadVCFContig(String contig)
   {
     VCFHeaderLine headerLine = header.getOtherHeaderLine(VCFHeader.REFERENCE_KEY);
-    String ref = headerLine == null ? null : headerLine.getValue();
+    if (headerLine == null)
+    {
+      Cache.log.error("VCF reference header not found");
+      return null;
+    }
+    String ref = headerLine.getValue();
     if (ref.startsWith("file://"))
     {
       ref = ref.substring(7);
@@ -282,7 +289,7 @@ public class VCFLoader
     }
     else
     {
-      System.err.println("VCF reference not found: " + ref);
+      Cache.log.error("VCF reference not found: " + ref);
     }
 
     return seq;
@@ -301,7 +308,7 @@ public class VCFLoader
     {
       VCFHeaderLine ref = header
               .getOtherHeaderLine(VCFHeader.REFERENCE_KEY);
-      String reference = ref.getValue();
+      String reference = ref == null ? null : ref.getValue();
 
       setSpeciesAndAssembly(reference);
 
@@ -373,8 +380,13 @@ public class VCFLoader
    */
   protected void setSpeciesAndAssembly(String reference)
   {
+    if (reference == null)
+    {
+      Cache.log.error("No VCF ##reference found, defaulting to "
+              + DEFAULT_REFERENCE + ":" + DEFAULT_SPECIES);
+      reference = DEFAULT_REFERENCE; // default to GRCh37 if not specified
+    }
     reference = reference.toLowerCase();
-    vcfSpecies = DEFAULT_SPECIES;
 
     /*
      * for a non-human species, or other assembly identifier,
@@ -397,6 +409,7 @@ public class VCFLoader
       }
     }
 
+    vcfSpecies = DEFAULT_SPECIES;
     prop = Cache.getProperty(VCF_SPECIES);
     if (prop != null)
     {
@@ -724,7 +737,7 @@ public class VCFLoader
     String species = seqCoords.getSpeciesId();
     String chromosome = seqCoords.getChromosomeId();
     String seqRef = seqCoords.getAssemblyId();
-    MapList map = seqCoords.getMap();
+    MapList map = seqCoords.getMapping();
 
     // note this requires the configured species to match that
     // returned with the Ensembl sequence; todo: support aliases?
index fe85043..f30fa9b 100755 (executable)
@@ -435,7 +435,7 @@ public class GDesktop extends JFrame
     FileMenu.add(inputMenu);
     FileMenu.add(inputSequence);
     FileMenu.addSeparator();
-    FileMenu.add(saveState);
+    //FileMenu.add(saveState);
     FileMenu.add(saveAsState);
     FileMenu.add(loadState);
     FileMenu.addSeparator();
index 87cc87b..60bf1b7 100755 (executable)
@@ -31,6 +31,8 @@ import jalview.gui.JvSwingUtils;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.BackupFilenameParts;
 import jalview.io.BackupFiles;
+import jalview.io.BackupFilesPresetEntry;
+import jalview.io.IntKeyStringValueEntry;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -51,8 +53,8 @@ import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Arrays;
+import java.util.List;
 
 import javax.swing.AbstractCellEditor;
 import javax.swing.BorderFactory;
@@ -63,7 +65,6 @@ import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JFileChooser;
 import javax.swing.JLabel;
-import javax.swing.JList;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
 import javax.swing.JScrollPane;
@@ -296,9 +297,15 @@ public class GPreferences extends JPanel
 
   protected JPanel presetsPanel = new JPanel();
 
+  protected JLabel presetsComboLabel = new JLabel();
+
+  protected JCheckBox customiseCheckbox = new JCheckBox();
+
   protected JButton revertButton = new JButton();
 
-  protected JComboBox<IntKeyStringValueEntry> backupfilesPresetsCombo = new JComboBox<>();
+  protected JComboBox<Object> backupfilesPresetsCombo = new JComboBox<>();
+
+  private int backupfilesPresetsComboLastSelected = 0;
 
   protected JPanel suffixPanel = new JPanel();
 
@@ -1695,22 +1702,28 @@ public class GPreferences extends JPanel
 
   protected void loadLastSavedBackupsOptions()
   {
+    BackupFilesPresetEntry savedPreset = BackupFilesPresetEntry
+            .getSavedBackupEntry();
     enableBackupFiles
             .setSelected(Cache.getDefault(BackupFiles.ENABLED, true));
+
+    BackupFilesPresetEntry backupfilesCustomEntry = BackupFilesPresetEntry
+            .createBackupFilesPresetEntry(Cache
+                    .getDefault(BackupFilesPresetEntry.CUSTOMCONFIG, null));
+    if (backupfilesCustomEntry == null)
+    {
+      backupfilesCustomEntry = BackupFilesPresetEntry.backupfilesPresetEntriesValues
+              .get(BackupFilesPresetEntry.BACKUPFILESSCHEMEDEFAULT);
+    }
+    BackupFilesPresetEntry.backupfilesPresetEntriesValues.put(
+            BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM,
+            backupfilesCustomEntry);
+
     setComboIntStringKey(backupfilesPresetsCombo,
-            Cache.getDefault(BackupFiles.NS + "_PRESET", 1));
-    suffixTemplate.setText(Cache.getDefault(BackupFiles.SUFFIX,
-            ".bak" + BackupFiles.NUM_PLACEHOLDER));
-    suffixDigitsSpinner
-            .setValue(Cache.getDefault(BackupFiles.SUFFIX_DIGITS, 3));
-    suffixReverse.setSelected(
-            Cache.getDefault(BackupFiles.REVERSE_ORDER, false));
-    backupfilesKeepAll
-            .setSelected(Cache.getDefault(BackupFiles.NO_MAX, false));
-    backupfilesRollMaxSpinner
-            .setValue(Cache.getDefault(BackupFiles.ROLL_MAX, 3));
-    backupfilesConfirmDelete.setSelected(
-            Cache.getDefault(BackupFiles.CONFIRM_DELETE_OLD, true));
+            Cache.getDefault(BackupFiles.NS + "_PRESET",
+                    BackupFilesPresetEntry.BACKUPFILESSCHEMEDEFAULT));
+
+    backupsSetOptions(savedPreset);
 
     backupsOptionsSetEnabled();
     updateBackupFilesExampleLabel();
@@ -1718,11 +1731,11 @@ public class GPreferences extends JPanel
 
   private boolean warnAboutSuffixReverseChange()
   {
-    boolean savedSuffixReverse = Cache.getDefault(BackupFiles.REVERSE_ORDER,
-            false);
-    int savedSuffixDigits = Cache.getDefault(BackupFiles.SUFFIX_DIGITS, 3);
-    String savedSuffixTemplate = Cache.getDefault(BackupFiles.SUFFIX,
-            ".bak" + BackupFiles.NUM_PLACEHOLDER);
+    BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
+            .getSavedBackupEntry();
+    boolean savedSuffixReverse = bfpe.reverse;
+    int savedSuffixDigits = bfpe.digits;
+    String savedSuffixTemplate = bfpe.suffix;
 
     boolean nowSuffixReverse = suffixReverse.isSelected();
     int nowSuffixDigits = getSpinnerInt(suffixDigitsSpinner, 3);
@@ -1799,7 +1812,6 @@ public class GPreferences extends JPanel
     gbc.gridy++; // row 1
     backupsTab.add(presetsPanel, gbc);
 
-    // gbc.anchor = GridBagConstraints.NORTHWEST;
     // now using whole row
     gbc.gridwidth = 2;
     gbc.gridheight = 1;
@@ -1821,50 +1833,10 @@ public class GPreferences extends JPanel
     return backupsTab;
   }
 
-  protected static final int BACKUPFILESSCHEMECUSTOMISE = 0;
-
-  private static final IntKeyStringValueEntry[] backupfilesPresetEntries = {
-      new IntKeyStringValueEntry(1,
-              MessageManager.getString("label.default")),
-      new IntKeyStringValueEntry(2,
-              MessageManager.getString("label.single_file")),
-      new IntKeyStringValueEntry(3,
-              MessageManager.getString("label.keep_all_versions")),
-      new IntKeyStringValueEntry(4,
-              MessageManager.getString("label.rolled_backups")),
-      // ...
-      // IMPORTANT, keep "Custom" entry with key 0 (even though it appears last)
-      new IntKeyStringValueEntry(BACKUPFILESSCHEMECUSTOMISE,
-              MessageManager.getString("label.customise")) };
-
-  private static final Map<Integer, BackupFilesPresetEntry> backupfilesPresetEntriesValues = new HashMap<Integer, BackupFilesPresetEntry>()
-  {
-    /**
-     * 
-     */
-    private static final long serialVersionUID = 125L;
-
-    {
-      put(1, new BackupFilesPresetEntry(
-              ".bak" + BackupFiles.NUM_PLACEHOLDER, 3, false, false, 3,
-              false));
-      put(2, new BackupFilesPresetEntry("~", 1, false, false, 1, false));
-      put(3, new BackupFilesPresetEntry(".v" + BackupFiles.NUM_PLACEHOLDER,
-              3, false, true, 10, true));
-      put(4, new BackupFilesPresetEntry(
-              "_bak." + BackupFiles.NUM_PLACEHOLDER, 1, true, false, 9,
-              false));
-    }
-  };
-
   private JPanel initBackupsTabPresetsPanel()
   {
 
     String title = MessageManager.getString("label.schemes");
-    // TitledBorder tb = new TitledBorder(new EmptyBorder(0, 0, 0, 0), title);
-    // TitledBorder tb = new TitledBorder(title);
-    // tb.setTitleFont(LABEL_FONT);
-    // presetsPanel.setBorder(tb);
 
     presetsPanel.setLayout(new GridBagLayout());
 
@@ -1879,24 +1851,53 @@ public class GPreferences extends JPanel
     // "Scheme: "
     gbc.gridx = 0;
     gbc.gridy = 0;
-    presetsPanel.add(new JLabel(title + ":"), gbc);
 
-    for (int i = 0; i < backupfilesPresetEntries.length; i++)
+    presetsComboLabel = new JLabel(title + ":");
+    presetsPanel.add(presetsComboLabel, gbc);
+
+    List<Object> entries = Arrays
+            .asList((Object[]) BackupFilesPresetEntry.backupfilesPresetEntries);
+    List<String> tooltips = Arrays.asList(
+            BackupFilesPresetEntry.backupfilesPresetEntryDescriptions);
+    backupfilesPresetsCombo = JvSwingUtils.buildComboWithTooltips(entries,
+            tooltips);
+    /*
+    for (int i = 0; i < BackupFilesPresetEntry.backupfilesPresetEntries.length; i++)
     {
-      backupfilesPresetsCombo.addItem(backupfilesPresetEntries[i]);
+      backupfilesPresetsCombo
+              .addItem(BackupFilesPresetEntry.backupfilesPresetEntries[i]);
     }
+    */
 
-    // put "Previously saved scheme" item in italics (it's not really
-    // selectable, as such -- it deselects itself when selected) and
-    // "Customise" in bold
-    backupfilesPresetsCombo
-            .setRenderer(new BackupFilesPresetsComboBoxRenderer());
     backupfilesPresetsCombo.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        backupsTabUpdatePresets();
+        int key = getComboIntStringKey(backupfilesPresetsCombo);
+        if (!customiseCheckbox.isSelected())
+        {
+          backupfilesPresetsComboLastSelected = key;
+        }
+        if (key == BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM)
+        {
+          if (customiseCheckbox.isSelected())
+          {
+            // got here by clicking on customiseCheckbox so don't change the values
+            backupfilesCustomOptionsSetEnabled();
+          }
+          else
+          {
+            backupsTabUpdatePresets();
+            backupfilesCustomOptionsSetEnabled();
+          }
+        }
+        else
+        {
+          customiseCheckbox.setSelected(false);
+          backupsTabUpdatePresets();
+          backupfilesCustomOptionsSetEnabled();
+        }
       }
     });
 
@@ -1905,20 +1906,55 @@ public class GPreferences extends JPanel
     presetsPanel.add(backupfilesPresetsCombo, gbc);
 
     revertButton.setText(MessageManager.getString("label.cancel_changes"));
+    revertButton.setToolTipText(
+            MessageManager.getString("label.cancel_changes_description"));
     revertButton.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        loadLastSavedBackupsOptions();
+        backupsSetOptions(
+                BackupFilesPresetEntry.backupfilesPresetEntriesValues.get(
+                        BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM));
+        backupfilesCustomOptionsSetEnabled();
       }
 
     });
     revertButton.setFont(LABEL_FONT);
 
+    customiseCheckbox.setFont(LABEL_FONT);
+    customiseCheckbox.setText(MessageManager.getString("label.customise"));
+    customiseCheckbox.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        int currently = getComboIntStringKey(backupfilesPresetsCombo);
+        if (customiseCheckbox.isSelected())
+        {
+          backupfilesPresetsComboLastSelected = currently;
+          setComboIntStringKey(backupfilesPresetsCombo,
+                  BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM);
+        }
+        else
+        {
+          setComboIntStringKey(backupfilesPresetsCombo,
+                  backupfilesPresetsComboLastSelected);
+
+        }
+        backupfilesCustomOptionsSetEnabled();
+      }
+    });
+    customiseCheckbox.setToolTipText(
+            MessageManager.getString("label.customise_description"));
+
+    // customise checkbox
+    gbc.gridx = 0;
+    gbc.gridy++;
+    presetsPanel.add(customiseCheckbox, gbc);
+
     // "Cancel changes" button (aligned with combo box above)
     gbc.gridx = 1;
-    gbc.gridy++;
     presetsPanel.add(revertButton, gbc);
 
     return presetsPanel;
@@ -1927,7 +1963,7 @@ public class GPreferences extends JPanel
   private JPanel initBackupsTabFilenameExamplesPanel()
   {
     String title = MessageManager
-            .getString("label.summary_of_backups_scheme");
+            .getString("label.scheme_examples");
     TitledBorder tb = new TitledBorder(title);
     exampleFilesPanel.setBorder(tb);
     exampleFilesPanel.setLayout(new GridBagLayout());
@@ -1953,45 +1989,68 @@ public class GPreferences extends JPanel
   {
     IntKeyStringValueEntry entry = (IntKeyStringValueEntry) backupfilesPresetsCombo
             .getSelectedItem();
-    int key = entry.getKey();
-    String value = entry.getValue();
+    int key = entry.k;
+    String value = entry.v;
 
-    // BACKUPFILESSCHEMECUSTOMISE (==0) reserved for "Custom"
-    if (key != BACKUPFILESSCHEMECUSTOMISE)
+    if (BackupFilesPresetEntry.backupfilesPresetEntriesValues
+            .containsKey(key))
     {
-      if (backupfilesPresetEntriesValues.containsKey(key))
-      {
-        backupsSetOptions(backupfilesPresetEntriesValues.get(key));
-      }
-      else
-      {
-        System.out.println("Preset '" + value + "' not implemented");
-      }
+      backupsSetOptions(
+              BackupFilesPresetEntry.backupfilesPresetEntriesValues
+                      .get(key));
+    }
+    else
+    {
+      Cache.log.error(
+              "Preset '" + value + "' [key:" + key + "] not implemented");
     }
 
-    backupfilesCustomOptionsSetEnabled();
+    // Custom options will now be enabled when the customiseCheckbox is checked
+    // (performed above)
+    // backupfilesCustomOptionsSetEnabled();
     updateBackupFilesExampleLabel();
   }
 
-  protected int getComboIntStringKey(JComboBox<IntKeyStringValueEntry> c)
+  protected int getComboIntStringKey(
+          JComboBox<Object> backupfilesPresetsCombo2)
   {
-    IntKeyStringValueEntry e = (IntKeyStringValueEntry) c.getSelectedItem();
-    return e != null ? e.getKey() : 0;
+    IntKeyStringValueEntry e;
+    try
+    {
+      e = (IntKeyStringValueEntry) backupfilesPresetsCombo2
+              .getSelectedItem();
+    } catch (Exception ex)
+    {
+      Cache.log.error(
+              "Problem casting Combo entry to IntKeyStringValueEntry.");
+      e = null;
+    }
+    return e != null ? e.k : 0;
   }
 
-  protected void setComboIntStringKey(JComboBox<IntKeyStringValueEntry> c,
+  protected void setComboIntStringKey(
+          JComboBox<Object> backupfilesPresetsCombo2,
           int key)
   {
-    for (int i = 0; i < c.getItemCount(); i++)
+    for (int i = 0; i < backupfilesPresetsCombo2.getItemCount(); i++)
     {
-      IntKeyStringValueEntry e = c.getItemAt(i);
-      if (e.getKey() == key)
+      IntKeyStringValueEntry e;
+      try
       {
-        c.setSelectedIndex(i);
+        e = (IntKeyStringValueEntry) backupfilesPresetsCombo2.getItemAt(i);
+      } catch (Exception ex)
+      {
+        Cache.log.error(
+                "Problem casting Combo entry to IntKeyStringValueEntry. Skipping item. ");
+        continue;
+      }
+      if (e.k == key)
+      {
+        backupfilesPresetsCombo2.setSelectedIndex(i);
         break;
       }
     }
-    backupsTabUpdatePresets();
+    // backupsTabUpdatePresets();
   }
 
   private JPanel initBackupsTabSuffixPanel()
@@ -2015,16 +2074,18 @@ public class GPreferences extends JPanel
       {
         updateBackupFilesExampleLabel();
         backupfilesCustomOptionsSetEnabled();
+        backupfilesRevertButtonSetEnabled(true);
       }
 
     });
-    KeyListener kl = new KeyListener()
+    suffixTemplate.addKeyListener(new KeyListener()
     {
       @Override
       public void keyReleased(KeyEvent e)
       {
         updateBackupFilesExampleLabel();
         backupfilesCustomOptionsSetEnabled();
+        backupfilesRevertButtonSetEnabled(true);
       }
 
       @Override
@@ -2044,26 +2105,25 @@ public class GPreferences extends JPanel
         }
       }
 
-    };
-    suffixTemplate.addKeyListener(kl);
+    });
 
     // digits spinner
     suffixDigitsLabel
             .setText(MessageManager.getString("label.index_digits"));
     suffixDigitsLabel.setHorizontalAlignment(SwingConstants.LEFT);
     suffixDigitsLabel.setFont(LABEL_FONT);
-    int defaultmin = 1;
-    int defaultmax = 6;
     ChangeListener c = new ChangeListener()
     {
       @Override
       public void stateChanged(ChangeEvent e)
       {
+        backupfilesRevertButtonSetEnabled(true);
         updateBackupFilesExampleLabel();
       }
 
     };
-    setIntegerSpinner(suffixDigitsSpinner, defaultmin, defaultmax, 3, c);
+    setIntegerSpinner(suffixDigitsSpinner, BackupFilesPresetEntry.DIGITSMIN,
+            BackupFilesPresetEntry.DIGITSMAX, 3, c);
 
     suffixReverse.setLabels(MessageManager.getString("label.reverse_roll"),
             MessageManager.getString("label.increment_index"));
@@ -2080,12 +2140,13 @@ public class GPreferences extends JPanel
         }
         if (okay)
         {
+          backupfilesRevertButtonSetEnabled(true);
           updateBackupFilesExampleLabel();
         }
         else
         {
-          boolean savedSuffixReverse = Cache
-                  .getDefault(BackupFiles.REVERSE_ORDER, false);
+          boolean savedSuffixReverse = BackupFilesPresetEntry
+                  .getSavedBackupEntry().reverse;
           suffixReverse.setSelected(savedSuffixReverse);
         }
       }
@@ -2161,6 +2222,7 @@ public class GPreferences extends JPanel
       @Override
       public void actionPerformed(ActionEvent e)
       {
+        backupfilesRevertButtonSetEnabled(true);
         updateBackupFilesExampleLabel();
       }
     });
@@ -2169,6 +2231,7 @@ public class GPreferences extends JPanel
       @Override
       public void actionPerformed(ActionEvent e)
       {
+        backupfilesRevertButtonSetEnabled(true);
         keepRollMaxOptionsEnabled();
         updateBackupFilesExampleLabel();
       }
@@ -2179,15 +2242,26 @@ public class GPreferences extends JPanel
       @Override
       public void stateChanged(ChangeEvent e)
       {
+        backupfilesRevertButtonSetEnabled(true);
         updateBackupFilesExampleLabel();
       }
 
     };
-    setIntegerSpinner(backupfilesRollMaxSpinner, 1, 999, 4, true, c);
+    setIntegerSpinner(backupfilesRollMaxSpinner,
+            BackupFilesPresetEntry.ROLLMAXMIN,
+            BackupFilesPresetEntry.ROLLMAXMAX, 4, true, c);
 
     backupfilesConfirmDelete.setLabels(
             MessageManager.getString("label.always_ask"),
             MessageManager.getString("label.auto_delete"));
+    backupfilesConfirmDelete.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        backupfilesRevertButtonSetEnabled(true);
+      }
+    });
     // update the enabled section
     keepRollMaxOptionsEnabled();
 
@@ -2223,13 +2297,6 @@ public class GPreferences extends JPanel
     kgbc.gridwidth = GridBagConstraints.REMAINDER;
     kgbc.fill = GridBagConstraints.HORIZONTAL;
     kgbc.weightx = 1.0;
-    /*
-    keepfilesPanel.add(backupfilesConfirmDelete.getTrueButton(), kgbc);
-    
-    // fourth row (indented)
-    kgbc.gridy = 3;
-    keepfilesPanel.add(backupfilesConfirmDelete.getFalseButton(), kgbc);
-    */
 
     JPanel jp = new JPanel();
     jp.setLayout(new FlowLayout());
@@ -2285,6 +2352,7 @@ public class GPreferences extends JPanel
     int uppersurround = 0;
     StringBuilder exampleSB = new StringBuilder();
     boolean firstLine = true;
+    int lineNumber = 0;
     if (reverse)
     {
 
@@ -2295,6 +2363,7 @@ public class GPreferences extends JPanel
         if (index == min + lowersurround && index < max - uppersurround - 1)
         {
           exampleSB.append("\n...");
+          lineNumber++;
         }
         else if (index > min + lowersurround && index < max - uppersurround)
         {
@@ -2309,6 +2378,7 @@ public class GPreferences extends JPanel
           else
           {
             exampleSB.append("\n");
+            lineNumber++;
           }
           exampleSB.append(BackupFilenameParts.getBackupFilename(index,
                   base, suffix, digits));
@@ -2348,6 +2418,7 @@ public class GPreferences extends JPanel
         if (index == min + lowersurround && index < max - uppersurround - 1)
         {
           exampleSB.append("\n...");
+          lineNumber++;
         }
         else if (index > min + lowersurround && index < max - uppersurround)
         {
@@ -2362,6 +2433,7 @@ public class GPreferences extends JPanel
           else
           {
             exampleSB.append("\n");
+            lineNumber++;
           }
           exampleSB.append(BackupFilenameParts.getBackupFilename(index,
                   base, suffix, digits));
@@ -2390,6 +2462,18 @@ public class GPreferences extends JPanel
 
     }
 
+    // add some extra empty lines to pad out the example files box. ugh, please tell
+    // me how to do this better
+    int remainingLines = lowersurround + uppersurround + 1 - lineNumber;
+    if (remainingLines > 0)
+    {
+      for (int i = 0; i < remainingLines; i++)
+      {
+        exampleSB.append("\n ");
+        lineNumber++;
+      }
+    }
+
     backupfilesExampleLabel.setText(exampleSB.toString());
   }
 
@@ -2404,7 +2488,7 @@ public class GPreferences extends JPanel
         i = Integer.parseInt((String) s.getValue());
       } catch (Exception e)
       {
-        System.out.println(
+        Cache.log.error(
                 "Exception casting the initial value of s.getValue()");
       }
     }
@@ -2436,7 +2520,7 @@ public class GPreferences extends JPanel
       i = (Integer) s.getValue();
     } catch (Exception e)
     {
-      System.out.println("Failed casting (Integer) JSpinner s.getValue()");
+      Cache.log.error("Failed casting (Integer) JSpinner s.getValue()");
     }
     return i;
   }
@@ -2453,7 +2537,7 @@ public class GPreferences extends JPanel
   private void backupfilesKeepAllSetEnabled(boolean tryEnabled)
   {
     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
-            && getComboIntStringKey(backupfilesPresetsCombo) == 0
+            && customiseCheckbox.isSelected()
             && suffixTemplate.getText()
                     .indexOf(BackupFiles.NUM_PLACEHOLDER) > -1;
     keepfilesPanel.setEnabled(enabled);
@@ -2474,18 +2558,48 @@ public class GPreferences extends JPanel
   private void backupfilesSuffixTemplateSetEnabled(boolean tryEnabled)
   {
     boolean enabled = tryEnabled && enableBackupFiles.isSelected()
-            && getComboIntStringKey(backupfilesPresetsCombo) == 0;
+            && customiseCheckbox.isSelected();
     suffixPanel.setEnabled(enabled);
     suffixTemplateLabel.setEnabled(enabled);
     suffixTemplate.setEnabled(enabled);
     backupfilesSuffixTemplateDigitsSetEnabled();
   }
 
+  private void backupfilesRevertButtonSetEnabled(boolean tryEnabled)
+  {
+    boolean enabled = tryEnabled && enableBackupFiles.isSelected()
+            && customiseCheckbox.isSelected() && backupfilesCustomChanged();
+    revertButton.setEnabled(enabled);
+  }
+
+  private boolean backupfilesCustomChanged()
+  {
+    BackupFilesPresetEntry custom = BackupFilesPresetEntry.backupfilesPresetEntriesValues
+            .get(BackupFilesPresetEntry.BACKUPFILESSCHEMECUSTOM);
+    BackupFilesPresetEntry current = getBackupfilesCurrentEntry();
+    return !custom.equals(current);
+  }
+
+  protected BackupFilesPresetEntry getBackupfilesCurrentEntry()
+  {
+    String suffix = suffixTemplate.getText();
+    int digits = getSpinnerInt(suffixDigitsSpinner, 3);
+    boolean reverse = suffixReverse.isSelected();
+    boolean keepAll = backupfilesKeepAll.isSelected();
+    int rollMax = getSpinnerInt(backupfilesRollMaxSpinner, 3);
+    boolean confirmDelete = backupfilesConfirmDelete.isSelected();
+
+    BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(suffix, digits,
+            reverse, keepAll, rollMax, confirmDelete);
+
+    return bfpe;
+  }
+
   protected void backupfilesCustomOptionsSetEnabled()
   {
-    int scheme = getComboIntStringKey(backupfilesPresetsCombo);
-    boolean enabled = scheme == 0 && enableBackupFiles.isSelected();
+    boolean enabled = customiseCheckbox.isSelected();
 
+    backupfilesRevertButtonSetEnabled(enabled);
     backupfilesSuffixTemplateSetEnabled(enabled);
     backupfilesKeepAllSetEnabled(enabled);
   }
@@ -2501,7 +2615,10 @@ public class GPreferences extends JPanel
   {
     boolean enabled = enableBackupFiles.isSelected();
     presetsPanel.setEnabled(enabled);
+    presetsComboLabel.setEnabled(enabled);
     backupfilesPresetsCombo.setEnabled(enabled);
+    customiseCheckbox.setEnabled(enabled);
+    revertButton.setEnabled(enabled);
   }
 
   protected void backupsOptionsSetEnabled()
@@ -2715,85 +2832,3 @@ public class GPreferences extends JPanel
   }
 }
 
-class IntKeyStringValueEntry
-{
-  int k;
-
-  String v;
-
-  public IntKeyStringValueEntry(int k, String v)
-  {
-    this.k = k;
-    this.v = v;
-  }
-
-  @Override
-  public String toString()
-  {
-    return this.getValue();
-  }
-
-  public int getKey()
-  {
-    return k;
-  }
-
-  public String getValue()
-  {
-    return v;
-  }
-}
-
-class BackupFilesPresetEntry
-{
-  String suffix;
-
-  int digits;
-
-  boolean reverse;
-
-  boolean keepAll;
-
-  int rollMax;
-
-  boolean confirmDelete;
-
-  public BackupFilesPresetEntry(String suffix, int digits, boolean reverse,
-          boolean keepAll, int rollMax, boolean confirmDelete)
-  {
-    this.suffix = suffix;
-    this.digits = digits;
-    this.reverse = reverse;
-    this.keepAll = keepAll;
-    this.rollMax = rollMax;
-    this.confirmDelete = confirmDelete;
-  }
-}
-
-class BackupFilesPresetsComboBoxRenderer extends DefaultListCellRenderer
-{
-  /**
-   * 
-   */
-  private static final long serialVersionUID = 88L;
-
-  @Override
-  public Component getListCellRendererComponent(JList list, Object value,
-          int index, boolean isSelected, boolean cellHasFocus)
-  {
-    super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
-    
-    try {
-      IntKeyStringValueEntry e = (IntKeyStringValueEntry) value;
-      if (e.getKey() == GPreferences.BACKUPFILESSCHEMECUSTOMISE)
-      {
-        // "Customise" item
-        this.setFont(this.getFont().deriveFont(Font.BOLD));
-      }
-    } catch (Exception e) {
-      return this;
-    }
-
-    return this;
-  }
-}
index 0d2ec68..0e17779 100644 (file)
@@ -38,6 +38,8 @@ import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.GeneLocus;
 import jalview.datamodel.GraphLine;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Point;
@@ -2505,21 +2507,29 @@ public class Jalview2XML
         parentseq = jds;
       }
     }
+
+    /*
+     * save any dbrefs; special subclass GeneLocus is flagged as 'locus'
+     */
     if (dbrefs != null)
     {
       for (int d = 0; d < dbrefs.length; d++)
       {
         DBRef dbref = new DBRef();
-        dbref.setSource(dbrefs[d].getSource());
-        dbref.setVersion(dbrefs[d].getVersion());
-        dbref.setAccessionId(dbrefs[d].getAccessionId());
-        if (dbrefs[d].hasMap())
+        DBRefEntry dbRefEntry = dbrefs[d];
+        dbref.setSource(dbRefEntry.getSource());
+        dbref.setVersion(dbRefEntry.getVersion());
+        dbref.setAccessionId(dbRefEntry.getAccessionId());
+        if (dbRefEntry instanceof GeneLocus)
         {
-          Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
+          dbref.setLocus(true);
+        }
+        if (dbRefEntry.hasMap())
+        {
+          Mapping mp = createVamsasMapping(dbRefEntry.getMap(), parentseq,
                   jds, recurse);
           dbref.setMapping(mp);
         }
-        // vamsasSeq.addDBRef(dbref);
         vamsasSeq.getDBRef().add(dbref);
       }
     }
@@ -5798,13 +5808,29 @@ public class Jalview2XML
     return datasetId;
   }
 
+  /**
+   * Add any saved DBRefEntry's to the sequence. An entry flagged as 'locus' is
+   * constructed as a special subclass GeneLocus.
+   * 
+   * @param datasetSequence
+   * @param sequence
+   */
   private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
   {
     for (int d = 0; d < sequence.getDBRef().size(); d++)
     {
       DBRef dr = sequence.getDBRef().get(d);
-      jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
-              dr.getSource(), dr.getVersion(), dr.getAccessionId());
+      DBRefEntry entry;
+      if (dr.isLocus())
+      {
+        entry = new GeneLocus(dr.getSource(), dr.getVersion(),
+                dr.getAccessionId());
+      }
+      else
+      {
+        entry = new DBRefEntry(dr.getSource(), dr.getVersion(),
+                dr.getAccessionId());
+      }
       if (dr.getMapping() != null)
       {
         entry.setMap(addMapping(dr.getMapping()));
index c1d8228..e8558fa 100644 (file)
@@ -132,7 +132,8 @@ public class Platform
         return false;
       }
       return (jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx() // .getMenuShortcutKeyMaskEx()
-              & e.getModifiersEx()) != 0; // getModifiers()) != 0;
+              & jalview.util.ShortcutKeyMaskExWrapper
+                      .getModifiersEx(e)) != 0; // getModifiers()) != 0;
     }
     return e.isControlDown();
   }
index 7292c80..c9ed231 100644 (file)
@@ -1,57 +1,46 @@
 package jalview.util;
 
-import java.awt.Toolkit;
-import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
 
 public class ShortcutKeyMaskExWrapper
 {
 
-  private static boolean init = false;
+  private static final Float specversion;
 
-  private static final Float specversion = Float
-          .parseFloat(System.getProperty("java.specification.version"));
+  private static final float modern;
 
-  private static final float modern = 11;
+  public static final int SHIFT_DOWN_MASK;
 
-  public static int SHIFT_DOWN_MASK = KeyEvent.SHIFT_DOWN_MASK;
+  public static final int ALT_DOWN_MASK;
 
-  public static int ALT_DOWN_MASK = KeyEvent.ALT_DOWN_MASK;
+  private static final ShortcutKeyMaskExWrapperI wrapper;
 
-  public ShortcutKeyMaskExWrapper()
+  static
   {
-  }
+    specversion = Float
+            .parseFloat(System.getProperty("java.specification.version"));
+    modern = 11;
 
-  private static void init()
-  {
-    if (init)
-    {
-      return;
-    }
-    if (specversion < modern)
+    if (specversion >= modern)
     {
-      SHIFT_DOWN_MASK = KeyEvent.SHIFT_MASK;
-      ALT_DOWN_MASK = KeyEvent.ALT_MASK;
+      wrapper = new ShortcutKeyMaskExWrapper11();
     }
     else
     {
-      SHIFT_DOWN_MASK = KeyEvent.SHIFT_DOWN_MASK;
-      ALT_DOWN_MASK = KeyEvent.ALT_DOWN_MASK;
+      wrapper = new ShortcutKeyMaskExWrapper8();
     }
-
-    init = true;
+    SHIFT_DOWN_MASK = wrapper.SHIFT_DOWN_MASK;
+    ALT_DOWN_MASK = wrapper.ALT_DOWN_MASK;
   }
 
   public static int getMenuShortcutKeyMaskEx()
   {
-    init();
-    if (specversion < modern)
-    {
-      return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-    }
-    else
-    {
-      return Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx();
-    }
+    return wrapper.getMenuShortcutKeyMaskEx();
+  }
+
+  public static int getModifiersEx(MouseEvent e)
+  {
+    return wrapper.getModifiersEx(e);
   }
 
 }
diff --git a/src/jalview/util/ShortcutKeyMaskExWrapper11.java b/src/jalview/util/ShortcutKeyMaskExWrapper11.java
new file mode 100644 (file)
index 0000000..41a6aa0
--- /dev/null
@@ -0,0 +1,34 @@
+package jalview.util;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.Toolkit;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+
+public class ShortcutKeyMaskExWrapper11 implements ShortcutKeyMaskExWrapperI
+{
+  public final static int SHIFT_DOWN_MASK = KeyEvent.SHIFT_DOWN_MASK;
+  public final static int ALT_DOWN_MASK = KeyEvent.ALT_DOWN_MASK;
+
+  @Override
+  public int getMenuShortcutKeyMaskEx()
+  {
+    try
+    {
+      if (!GraphicsEnvironment.isHeadless())
+      {
+        return Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx();
+      }
+    } catch (java.lang.Throwable t)
+    {
+    }
+    return 0;
+  }
+
+  @Override
+  public int getModifiersEx(MouseEvent e)
+  {
+    return e.getModifiersEx();
+  }
+
+}
diff --git a/src/jalview/util/ShortcutKeyMaskExWrapper8.java b/src/jalview/util/ShortcutKeyMaskExWrapper8.java
new file mode 100644 (file)
index 0000000..78254b5
--- /dev/null
@@ -0,0 +1,34 @@
+package jalview.util;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.Toolkit;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+
+public class ShortcutKeyMaskExWrapper8 implements ShortcutKeyMaskExWrapperI
+{
+  public final static int SHIFT_DOWN_MASK = KeyEvent.SHIFT_MASK;
+  public final static int ALT_DOWN_MASK = KeyEvent.ALT_MASK;
+
+  @Override
+  public int getMenuShortcutKeyMaskEx()
+  {
+    try
+    {
+      if (!GraphicsEnvironment.isHeadless())
+      {
+        return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+      }
+    } catch (java.lang.Throwable t)
+    {
+    }
+    return 0;
+  }
+
+  @Override
+  public int getModifiersEx(MouseEvent e)
+  {
+    return e.getModifiers();
+  }
+
+}
diff --git a/src/jalview/util/ShortcutKeyMaskExWrapperI.java b/src/jalview/util/ShortcutKeyMaskExWrapperI.java
new file mode 100644 (file)
index 0000000..bf17259
--- /dev/null
@@ -0,0 +1,14 @@
+package jalview.util;
+
+import java.awt.event.MouseEvent;
+
+public interface ShortcutKeyMaskExWrapperI
+{
+  public static int SHIFT_DOWN_MASK = 0;
+
+  public static int ALT_DOWN_MASK = 0;
+
+  public int getMenuShortcutKeyMaskEx();
+
+  public int getModifiersEx(MouseEvent e);
+}
index 83f1ee2..cb90984 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 0dbcad0..35f78f3 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 44affa2..6f5ef65 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index de408d2..6780323 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index b4c07bc..5edb2e8 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index e2592ab..68ebf9b 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 9001ee2..39fc0c3 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 0daf56a..c92f72c 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index bf69d5b..0c21215 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 5684acf..36b454f 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index ed57edc..0ea2491 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
@@ -208,6 +208,8 @@ import javax.xml.datatype.XMLGregorianCalendar;
  *                   &lt;attribute name="textColThreshold" type="{http://www.w3.org/2001/XMLSchema}int" />
  *                   &lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}ID" />
  *                   &lt;attribute name="complementId" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                   &lt;attribute name="showComplementFeatures" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *                   &lt;attribute name="showComplementFeaturesOnTop" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
  *                 &lt;/restriction>
  *               &lt;/complexContent>
  *             &lt;/complexType>
@@ -4808,6 +4810,8 @@ public class JalviewModel {
      *       &lt;attribute name="textColThreshold" type="{http://www.w3.org/2001/XMLSchema}int" />
      *       &lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}ID" />
      *       &lt;attribute name="complementId" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       &lt;attribute name="showComplementFeatures" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+     *       &lt;attribute name="showComplementFeaturesOnTop" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
      *     &lt;/restriction>
      *   &lt;/complexContent>
      * &lt;/complexType>
@@ -4914,6 +4918,10 @@ public class JalviewModel {
         protected String id;
         @XmlAttribute(name = "complementId")
         protected String complementId;
+        @XmlAttribute(name = "showComplementFeatures")
+        protected Boolean showComplementFeatures;
+        @XmlAttribute(name = "showComplementFeaturesOnTop")
+        protected Boolean showComplementFeaturesOnTop;
         @XmlAttribute(name = "width")
         protected Integer width;
         @XmlAttribute(name = "height")
@@ -6034,6 +6042,62 @@ public class JalviewModel {
         }
 
         /**
+         * Gets the value of the showComplementFeatures property.
+         * 
+         * @return
+         *     possible object is
+         *     {@link Boolean }
+         *     
+         */
+        public boolean isShowComplementFeatures() {
+            if (showComplementFeatures == null) {
+                return false;
+            } else {
+                return showComplementFeatures;
+            }
+        }
+
+        /**
+         * Sets the value of the showComplementFeatures property.
+         * 
+         * @param value
+         *     allowed object is
+         *     {@link Boolean }
+         *     
+         */
+        public void setShowComplementFeatures(Boolean value) {
+            this.showComplementFeatures = value;
+        }
+
+        /**
+         * Gets the value of the showComplementFeaturesOnTop property.
+         * 
+         * @return
+         *     possible object is
+         *     {@link Boolean }
+         *     
+         */
+        public boolean isShowComplementFeaturesOnTop() {
+            if (showComplementFeaturesOnTop == null) {
+                return false;
+            } else {
+                return showComplementFeaturesOnTop;
+            }
+        }
+
+        /**
+         * Sets the value of the showComplementFeaturesOnTop property.
+         * 
+         * @param value
+         *     allowed object is
+         *     {@link Boolean }
+         *     
+         */
+        public void setShowComplementFeaturesOnTop(Boolean value) {
+            this.showComplementFeaturesOnTop = value;
+        }
+
+        /**
          * Gets the value of the width property.
          * 
          * @return
index 701647c..c43e04c 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 3d7b5eb..1a31d82 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 3cbebc0..5ebeb7e 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
@@ -10,6 +10,7 @@ package jalview.xml.binding.jalview;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
@@ -41,6 +42,7 @@ import javax.xml.bind.annotation.XmlType;
  *           &lt;/element>
  *         &lt;/choice>
  *       &lt;/sequence>
+ *       &lt;attribute name="mappingType" type="{http://www.w3.org/2001/XMLSchema}string" />
  *     &lt;/extension>
  *   &lt;/complexContent>
  * &lt;/complexType>
@@ -61,6 +63,8 @@ public class Mapping
     @XmlElement(name = "Sequence")
     protected Sequence sequence;
     protected String dseqFor;
+    @XmlAttribute(name = "mappingType")
+    protected String mappingType;
 
     /**
      * Gets the value of the sequence property.
@@ -110,4 +114,28 @@ public class Mapping
         this.dseqFor = value;
     }
 
+    /**
+     * Gets the value of the mappingType property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getMappingType() {
+        return mappingType;
+    }
+
+    /**
+     * Sets the value of the mappingType property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setMappingType(String value) {
+        this.mappingType = value;
+    }
+
 }
index 15fc45d..9db4ea3 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 6858f07..e0b2127 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index e8c7cf2..6234f32 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 843ea6c..d5132ab 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index abb40c9..b842947 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
@@ -38,12 +38,14 @@ import javax.xml.bind.annotation.XmlType;
  *                 &lt;attribute name="source" type="{http://www.w3.org/2001/XMLSchema}string" />
  *                 &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
  *                 &lt;attribute name="accessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                 &lt;attribute name="locus" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
  *               &lt;/restriction>
  *             &lt;/complexContent>
  *           &lt;/complexType>
  *         &lt;/element>
  *       &lt;/sequence>
  *       &lt;attribute name="dsseqid" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="biotype" type="{http://www.w3.org/2001/XMLSchema}string" />
  *     &lt;/extension>
  *   &lt;/complexContent>
  * &lt;/complexType>
@@ -64,6 +66,8 @@ public class Sequence
     protected List<Sequence.DBRef> dbRef;
     @XmlAttribute(name = "dsseqid")
     protected String dsseqid;
+    @XmlAttribute(name = "biotype")
+    protected String biotype;
 
     /**
      * Gets the value of the dbRef property.
@@ -118,6 +122,30 @@ public class Sequence
         this.dsseqid = value;
     }
 
+    /**
+     * Gets the value of the biotype property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getBiotype() {
+        return biotype;
+    }
+
+    /**
+     * Sets the value of the biotype property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setBiotype(String value) {
+        this.biotype = value;
+    }
+
 
     /**
      * <p>Java class for anonymous complex type.
@@ -134,6 +162,7 @@ public class Sequence
      *       &lt;attribute name="source" type="{http://www.w3.org/2001/XMLSchema}string" />
      *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
      *       &lt;attribute name="accessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       &lt;attribute name="locus" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
      *     &lt;/restriction>
      *   &lt;/complexContent>
      * &lt;/complexType>
@@ -155,6 +184,8 @@ public class Sequence
         protected String version;
         @XmlAttribute(name = "accessionId")
         protected String accessionId;
+        @XmlAttribute(name = "locus")
+        protected Boolean locus;
 
         /**
          * Gets the value of the mapping property.
@@ -252,6 +283,34 @@ public class Sequence
             this.accessionId = value;
         }
 
+        /**
+         * Gets the value of the locus property.
+         * 
+         * @return
+         *     possible object is
+         *     {@link Boolean }
+         *     
+         */
+        public boolean isLocus() {
+            if (locus == null) {
+                return false;
+            } else {
+                return locus;
+            }
+        }
+
+        /**
+         * Sets the value of the locus property.
+         * 
+         * @param value
+         *     allowed object is
+         *     {@link Boolean }
+         *     
+         */
+        public void setLocus(Boolean value) {
+            this.locus = value;
+        }
+
     }
 
 }
index 0fc7771..6aee6ac 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 07b8c24..aef7543 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index e8b7e28..1b3d6d4 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index 1f68de9..5d341c3 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index c884556..659eab9 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 
index bd6dc77..3ed532d 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2018.12.20 at 11:47:26 AM GMT 
+// Generated on: 2019.06.07 at 02:21:15 PM BST 
 //
 
 @javax.xml.bind.annotation.XmlSchema(namespace = "www.vamsas.ac.uk/jalview/version2", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
index 70ae6a0..14559dd 100644 (file)
@@ -2684,7 +2684,7 @@ public class AlignmentUtilsTests
      * transcript 'CDS' is 10-16, 17-21
      * which is 'gene' 158-164, 210-214
      */
-    MapList toMap = toLoci.getMap();
+    MapList toMap = toLoci.getMapping();
     assertEquals(1, toMap.getFromRanges().size());
     assertEquals(2, toMap.getFromRanges().get(0).length);
     assertEquals(1, toMap.getFromRanges().get(0)[0]);
@@ -2707,7 +2707,7 @@ public class AlignmentUtilsTests
     AlignmentUtils.transferGeneLoci(from, map, to);
     assertEquals("GRCh38", toLoci.getAssemblyId());
     assertEquals("7", toLoci.getChromosomeId());
-    toMap = toLoci.getMap();
+    toMap = toLoci.getMapping();
     assertEquals("[ [1, 12] ] 1:1 to [ [158, 164] [210, 214] ]",
             toMap.toString());
   }
index 571c75b..cd0b594 100644 (file)
@@ -39,8 +39,9 @@ import jalview.gui.SeqPanel.MousePos;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
 import jalview.util.MessageManager;
+import jalview.viewmodel.ViewportRanges;
 
-import java.awt.event.InputEvent;import java.awt.EventQueue;
+import java.awt.EventQueue;
 import java.awt.event.MouseEvent;
 import java.lang.reflect.InvocationTargetException;
 
@@ -722,7 +723,8 @@ public class SeqPanelTest
     int x = 0;
     final int charWidth = alignFrame.getViewport().getCharWidth();
     assertTrue(charWidth > 0); // sanity check
-    assertEquals(alignFrame.getViewport().getRanges().getStartRes(), 0);
+    ViewportRanges ranges = alignFrame.getViewport().getRanges();
+    assertEquals(ranges.getStartRes(), 0);
 
     /*
      * mouse at top left of unwrapped panel
@@ -763,8 +765,10 @@ public class SeqPanelTest
             false, 0);
     SeqCanvas seqCanvas = alignFrame.alignPanel.getSeqPanel().seqCanvas;
     int w = seqCanvas.getWidth();
-    // limited to number of whole columns, base 0
-    int expected = w / charWidth - 1;
+    // limited to number of whole columns, base 0,
+    // and to end of visible range
+    int expected = w / charWidth;
+    expected = Math.min(expected, ranges.getEndRes());
     assertEquals(testee.findColumn(evt), expected);
 
     /*
index 723279d..64cf902 100644 (file)
@@ -34,7 +34,8 @@ public class BackupFilesTest
   }
 
   private static boolean actuallyDeleteTmpFiles = true;
-  private static String testDir = "examples";
+
+  private static String testDir = "test/jalview/io";
 
   private static String testBasename = "backupfilestest";
 
@@ -61,7 +62,7 @@ public class BackupFilesTest
 
   private static String suffix = "_BACKUPTEST-%n";
 
-  private static int digits = 8;
+  private static int digits = 6;
 
   private static int rollMax = 2;
 
@@ -107,28 +108,28 @@ public class BackupFilesTest
     }
 
     // check 10 backup files
-    HashMap correctindexmap = new HashMap();
-    correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-00000001");
-    correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-00000002");
-    correctindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-00000003");
-    correctindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-00000004");
-    correctindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-00000005");
-    correctindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-00000006");
-    correctindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-00000007");
-    correctindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-00000008");
-    correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-00000009");
-    correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-00000010");
-    HashMap wrongindexmap = new HashMap();
+    HashMap<Integer, String> correctindexmap = new HashMap<>();
+    correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-000001");
+    correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002");
+    correctindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-000003");
+    correctindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-000004");
+    correctindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-000005");
+    correctindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-000006");
+    correctindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-000007");
+    correctindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-000008");
+    correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009");
+    correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010");
+    HashMap<Integer, String> wrongindexmap = new HashMap<>();
     wrongindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-1");
-    wrongindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-00000002");
-    wrongindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-00000003");
-    wrongindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-00000004");
-    wrongindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-00000005");
-    wrongindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-00000006");
-    wrongindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-00000007");
-    wrongindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-00000008");
-    wrongindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-00000009");
-    wrongindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-00000010");
+    wrongindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002");
+    wrongindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-000003");
+    wrongindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-000004");
+    wrongindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-000005");
+    wrongindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-000006");
+    wrongindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-000007");
+    wrongindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-000008");
+    wrongindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009");
+    wrongindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010");
     int[] indexes2 = { 3, 4, 5, 6, 7, 8, 9, 10 };
     int[] indexes3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
     Assert.assertTrue(checkBackupFiles(correctindexmap));
@@ -158,9 +159,9 @@ public class BackupFilesTest
 
     // check there are "rollMax" backup files and they are all saved correctly
     // check 10 backup files
-    HashMap correctindexmap = new HashMap();
-    correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-00000009");
-    correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-00000010");
+    HashMap<Integer, String> correctindexmap = new HashMap<>();
+    correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009");
+    correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010");
     int[] indexes2 = { 10 };
     int[] indexes3 = { 8, 9, 10 };
     Assert.assertTrue(checkBackupFiles(correctindexmap));
@@ -189,9 +190,9 @@ public class BackupFilesTest
 
     // check there are "rollMax" backup files and they are all saved correctly
     // check 10 backup files
-    HashMap correctindexmap = new HashMap();
-    correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-00000001");
-    correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-00000002");
+    HashMap<Integer, String> correctindexmap = new HashMap<>();
+    correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-000001");
+    correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002");
     int[] indexes2 = { 1 };
     int[] indexes3 = { 1, 2, 3 };
     Assert.assertTrue(checkBackupFiles(correctindexmap));
@@ -209,6 +210,14 @@ public class BackupFilesTest
   {
     Cache.loadProperties("test/jalview/io/testProps.jvprops");
 
+    BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(suffix, digits,
+            reverse, noMax, rollMax, false);
+
+    Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
+            Boolean.toString(enabled));
+    Cache.applicationProperties.setProperty(
+            BackupFilesPresetEntry.SAVEDCONFIG, bfpe.toString());
+    /*
     Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
             Boolean.toString(enabled));
     Cache.applicationProperties.setProperty(BackupFiles.SUFFIX, suffix);
@@ -222,6 +231,7 @@ public class BackupFilesTest
             Integer.toString(rollMax));
     Cache.applicationProperties.setProperty(BackupFiles.CONFIRM_DELETE_OLD,
             "false");
+            */
   }
 
   private void save()
index f180395..94bc5d9 100644 (file)
@@ -1,13 +1,10 @@
 #---JalviewX Properties File---
 #Fri Apr 25 09:54:25 BST 2014
 #
-BACKUPFILES_ROLL_MAX=2
-BACKUPFILES_REVERSE_ORDER=false
-BACKUPFILES_SUFFIX=_BACKUPFILESTESTTMP%n
-BACKUPFILES_CONFIRM_DELETE_OLD=false
-BACKUPFILES_NO_MAX=false
 BACKUPFILES_ENABLED=true
-BACKUPFILES_SUFFIX_DIGITS=8
+BACKUPFILES_PRESET=0
+BACKUPFILES_SAVED=_BACKUPFILESTESTTMP%n\t6\tfalse\tfalse\t2\tfalse
+BACKUPFILES_CUSTOM=_BACKUPFILESTESTTMP%n\t6\tfalse\tfalse\t2\tfalse
 SCREEN_Y=768
 SCREEN_X=936
 SHOW_WSDISCOVERY_ERRORS=true
index d902fa2..5f1256c 100644 (file)
@@ -34,7 +34,10 @@ import jalview.api.FeatureColourI;
 import jalview.api.ViewStyleI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.GeneLocus;
 import jalview.datamodel.HiddenSequences;
+import jalview.datamodel.Mapping;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry.Type;
 import jalview.datamodel.SequenceCollectionI;
@@ -68,6 +71,7 @@ import jalview.schemes.RNAHelicesColour;
 import jalview.schemes.StrandColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
 import jalview.structure.StructureImportSettings;
+import jalview.util.MapList;
 import jalview.util.matcher.Condition;
 import jalview.viewmodel.AlignmentViewport;
 
@@ -1179,4 +1183,83 @@ public class Jalview2xmlTests extends Jalview2xmlBase
                     .getAlignViewport(),
             "Didn't restore correct view association for the PCA view");
   }
+
+  /**
+   * Test save and reload of DBRefEntry including GeneLocus in project
+   * 
+   * @throws Exception
+   */
+  @Test(groups = { "Functional" })
+  public void testStoreAndRecoverGeneLocus() throws Exception
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+    String seqData = ">P30419\nACDE\n>X1235\nGCCTGTGACGAA";
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
+            DataSourceType.PASTE);
+    assertNotNull(af, "Didn't read in the example file correctly.");
+  
+    AlignmentViewPanel ap = Desktop.getAlignmentPanels(null)[0];
+    SequenceI pep = ap.getAlignment().getSequenceAt(0);
+    SequenceI cds = ap.getAlignment().getSequenceAt(1);
+
+    /*
+     * give 'protein' a dbref to self, a dbref with map to CDS,
+     * and a dbref with map to gene 'locus'
+     */
+    DBRefEntry dbref1 = new DBRefEntry("Uniprot", "1", "P30419", null);
+    pep.addDBRef(dbref1);
+    Mapping cdsmap = new Mapping(cds,
+            new MapList(new int[]
+            { 1, 4 }, new int[] { 1, 12 }, 1, 3));
+    DBRefEntry dbref2 = new DBRefEntry("EMBLCDS", "2", "X1235", cdsmap);
+    pep.addDBRef(dbref2);
+    Mapping locusmap = new Mapping(null,
+            new MapList(new int[]
+            { 1, 4 }, new int[] { 2674123, 2674135 }, 1, 3));
+    DBRefEntry dbref3 = new GeneLocus("human", "GRCh38", "5", locusmap);
+    pep.addDBRef(dbref3);
+
+    File tfile = File.createTempFile("testStoreAndRecoverGeneLocus",
+            ".jvp");
+    try
+    {
+      new Jalview2XML(false).saveState(tfile);
+    } catch (Throwable e)
+    {
+      Assert.fail("Didn't save the state", e);
+    }
+    Desktop.instance.closeAll_actionPerformed(null);
+  
+    new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
+    AlignmentViewPanel rap = Desktop.getAlignmentPanels(null)[0];
+    SequenceI rpep = rap.getAlignment().getSequenceAt(0);
+    assertEquals(rpep.getName(), "P30419");
+    DBRefEntry[] dbrefs = rpep.getDBRefs();
+    assertEquals(dbrefs.length, 3);
+    DBRefEntry dbRef = dbrefs[0];
+    assertFalse(dbRef instanceof GeneLocus);
+    assertNull(dbRef.getMap());
+    assertEquals(dbRef, dbref1);
+
+    /*
+     * restored dbrefs with mapping have a different 'map to'
+     * sequence but otherwise match the original dbrefs
+     */
+    dbRef = dbrefs[1];
+    assertFalse(dbRef instanceof GeneLocus);
+    assertTrue(dbRef.equalRef(dbref2));
+    assertNotNull(dbRef.getMap());
+    SequenceI rcds = rap.getAlignment().getSequenceAt(1);
+    assertSame(dbRef.getMap().getTo(), rcds);
+    // compare MapList but not map.to
+    assertEquals(dbRef.getMap().getMap(), dbref2.getMap().getMap());
+
+    /*
+     * GeneLocus map.to is null so can compare Mapping objects
+     */
+    dbRef = dbrefs[2];
+    assertTrue(dbRef instanceof GeneLocus);
+    assertEquals(dbRef, dbref3);
+  }
 }
index 1279b31..dee5322 100644 (file)
@@ -282,9 +282,10 @@ public class HelpLinksChecker implements BufferedLineReader.LineCleaner
         else
         {
           internalHrefCount++;
+          String relFile = System.getProperty("os.name").indexOf("Win") > -1 ? href.replace("/", File.separator) : href;
           File hrefFile = href.equals("") ? htmlFile : new File(htmlFolder,
                   href);
-          if (hrefFile != htmlFile && !fileExists(hrefFile, href))
+          if (hrefFile != htmlFile && !fileExists(hrefFile, relFile))
           {
             badLink = true;
             invalidInternalHrefCount++;
index 374da46..21fc79e 100644 (file)
Binary files a/utils/install4j/DS_Store and b/utils/install4j/DS_Store differ
diff --git a/utils/install4j/DS_Store_1 b/utils/install4j/DS_Store_1
new file mode 100644 (file)
index 0000000..374da46
Binary files /dev/null and b/utils/install4j/DS_Store_1 differ
diff --git a/utils/install4j/DS_Store_2 b/utils/install4j/DS_Store_2
new file mode 100644 (file)
index 0000000..2eafdbc
Binary files /dev/null and b/utils/install4j/DS_Store_2 differ
diff --git a/utils/install4j/DS_Store_3 b/utils/install4j/DS_Store_3
new file mode 100644 (file)
index 0000000..21fc79e
Binary files /dev/null and b/utils/install4j/DS_Store_3 differ
diff --git a/utils/install4j/Uninstall Old Jalview.app/Contents/Info.plist b/utils/install4j/Uninstall Old Jalview.app/Contents/Info.plist
new file mode 100644 (file)
index 0000000..06399cf
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleAllowMixedLocalizations</key>
+       <true/>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>applet</string>
+       <key>CFBundleIconFile</key>
+       <string>applet</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.ScriptEditor.id.Uninstall-Old-Jalview--optional</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>Uninstall Old Jalview (optional)</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.0</string>
+       <key>CFBundleSignature</key>
+       <string>aplt</string>
+       <key>LSMinimumSystemVersionByArchitecture</key>
+       <dict>
+               <key>x86_64</key>
+               <string>10.6</string>
+       </dict>
+       <key>LSRequiresCarbon</key>
+       <true/>
+       <key>WindowState</key>
+       <dict>
+               <key>bundleDividerCollapsed</key>
+               <true/>
+               <key>bundlePositionOfDivider</key>
+               <real>0.0</real>
+               <key>dividerCollapsed</key>
+               <false/>
+               <key>eventLogLevel</key>
+               <integer>2</integer>
+               <key>name</key>
+               <string>ScriptWindowState</string>
+               <key>positionOfDivider</key>
+               <real>421</real>
+               <key>savedFrame</key>
+               <string>20 1180 700 672 0 0 3360 1867 </string>
+               <key>selectedTab</key>
+               <string>description</string>
+       </dict>
+</dict>
+</plist>
diff --git a/utils/install4j/Uninstall Old Jalview.app/Contents/MacOS/applet b/utils/install4j/Uninstall Old Jalview.app/Contents/MacOS/applet
new file mode 100755 (executable)
index 0000000..171d0cc
Binary files /dev/null and b/utils/install4j/Uninstall Old Jalview.app/Contents/MacOS/applet differ
diff --git a/utils/install4j/Uninstall Old Jalview.app/Contents/PkgInfo b/utils/install4j/Uninstall Old Jalview.app/Contents/PkgInfo
new file mode 100644 (file)
index 0000000..3253614
--- /dev/null
@@ -0,0 +1 @@
+APPLaplt
\ No newline at end of file
diff --git a/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/Scripts/main.scpt b/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/Scripts/main.scpt
new file mode 100644 (file)
index 0000000..7afbebc
Binary files /dev/null and b/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/Scripts/main.scpt differ
diff --git a/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.icns b/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.icns
new file mode 100644 (file)
index 0000000..67a2cbd
Binary files /dev/null and b/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.icns differ
diff --git a/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.rsrc b/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.rsrc
new file mode 100644 (file)
index 0000000..cf9920e
Binary files /dev/null and b/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/applet.rsrc differ
diff --git a/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/description.rtfd/TXT.rtf b/utils/install4j/Uninstall Old Jalview.app/Contents/Resources/description.rtfd/TXT.rtf
new file mode 100644 (file)
index 0000000..76ac711
--- /dev/null
@@ -0,0 +1,5 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
+{\fonttbl}
+{\colortbl;\red255\green255\blue255;}
+{\*\expandedcolortbl;;}
+}
\ No newline at end of file
diff --git a/utils/install4j/Uninstall Old Jalview.scpt b/utils/install4j/Uninstall Old Jalview.scpt
new file mode 100644 (file)
index 0000000..7afbebc
Binary files /dev/null and b/utils/install4j/Uninstall Old Jalview.scpt differ
index 7a924e2..bec9829 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <install4j version="7.0.9" transformSequenceNumber="7">
-  <directoryPresets config="../../../../../buildtools/jre/openjdk-java_vm/macos-jdk8u202-b08-jre" />
+  <directoryPresets config="." />
   <application name="Jalview" distributionSourceDir="" applicationId="6595-2347-1923-0725" mediaDir="../../build/install4j" mediaFilePattern="${compiler:sys.shortName}_${compiler:sys.platform}_${compiler:sys.version}" compression="6" lzmaCompression="true" pack200Compression="false" excludeSignedFromPacking="true" commonExternalFiles="false" createMd5Sums="true" shrinkRuntime="true" shortName="Jalview" publisher="University of Dundee" publisherWeb="http://www.jalview.org/" version="$$VERSION$$" allPathsRelative="true" backupOnSave="false" autoSave="false" convertDotsToUnderscores="true" macSignature="????" macVolumeId="5aac4968c304f65" javaMinVersion="9999999999" javaMaxVersion="" allowBetaVM="true" jdkMode="jdk" jdkName="JDK 11.0">
     <languages skipLanguageSelection="false" languageSelectionInPrincipalLanguage="false">
       <principalLanguage id="en" customLocalizationFile="" />
@@ -8,6 +8,8 @@
     </languages>
     <searchSequence>
       <directory location="${compiler:JRE_DIR}" />
+      <registry />
+      <envVar name="JAVA_HOME" />
     </searchSequence>
     <variables>
       <variable name="OSX_KEYSTORE" value="" description="" category="" />
       <fileset name="Full file set" id="734" customizedId="" />
       <fileset name="Mac OS X JRE" id="880" customizedId="" />
       <fileset name="Windows JRE" id="882" customizedId="" />
+      <fileset name="Jalview application" id="1873" customizedId="" />
+      <fileset name="MacOS Old Jalview Uninstaller" id="2105" customizedId="" />
     </filesets>
     <roots>
       <root id="735" fileset="734" location="" />
       <root id="881" fileset="880" location="" />
       <root id="883" fileset="882" location="" />
+      <root id="1874" fileset="1873" location="" />
+      <root id="2106" fileset="2105" location="" />
     </roots>
     <mountPoints>
       <mountPoint id="454" root="" location="" mode="755" />
       <mountPoint id="736" root="735" location="" mode="755" />
       <mountPoint id="884" root="881" location="" mode="755" />
       <mountPoint id="885" root="883" location="" mode="755" />
+      <mountPoint id="1875" root="1874" location="" mode="755" />
+      <mountPoint id="2107" root="2106" location="" mode="755" />
     </mountPoints>
     <entries>
       <dirEntry mountPoint="454" file="../../getdown/files/$$JAVA_VERSION$$" overwriteMode="4" shared="false" fileMode="644" uninstallMode="2" overrideFileMode="false" overrideOverwriteMode="true" overrideUninstallMode="true" entryMode="direct" subDirectory="files" excludeSuffixes="" dirMode="755" overrideDirMode="false">
       <dirEntry mountPoint="885" file="$$WINDOWS_JAVA_VM_DIR$$" overwriteMode="4" shared="false" fileMode="755" uninstallMode="0" overrideFileMode="true" overrideOverwriteMode="false" overrideUninstallMode="true" entryMode="subdir" subDirectory="${compiler:JRE_DIR}" excludeSuffixes="" dirMode="755" overrideDirMode="false">
         <exclude />
       </dirEntry>
+      <dirEntry mountPoint="1875" file="../../getdown/website/$$JAVA_VERSION$$/dist" overwriteMode="1" shared="false" fileMode="644" uninstallMode="2" overrideFileMode="true" overrideOverwriteMode="true" overrideUninstallMode="true" entryMode="subdir" subDirectory="dist" excludeSuffixes="" dirMode="755" overrideDirMode="true">
+        <exclude />
+      </dirEntry>
+      <dirEntry mountPoint="2107" file="Uninstall Old Jalview.app" overwriteMode="4" shared="false" fileMode="755" uninstallMode="0" overrideFileMode="true" overrideOverwriteMode="false" overrideUninstallMode="false" entryMode="subdir" subDirectory="Uninstall Old Jalview.app" excludeSuffixes="" dirMode="755" overrideDirMode="true">
+        <exclude />
+      </dirEntry>
     </entries>
     <components>
       <component name="jalview_getdown" id="1031" customizedId="" displayDescription="false" hideHelpButton="false" selected="true" changeable="true" downloadable="false" hidden="false">
         </include>
         <dependencies />
       </component>
+      <component name="jalview" id="1881" customizedId="" displayDescription="false" hideHelpButton="false" selected="true" changeable="true" downloadable="false" hidden="false">
+        <description />
+        <include all="false">
+          <entry location=".i4j_fileset_1873" fileType="regular" />
+        </include>
+        <dependencies />
+      </component>
+      <component name="macos_old_jalview_uninstaller" id="2110" customizedId="" displayDescription="false" hideHelpButton="false" selected="true" changeable="true" downloadable="false" hidden="false">
+        <description />
+        <include all="false">
+          <entry location=".i4j_fileset_2105" fileType="regular" />
+        </include>
+        <dependencies />
+      </component>
     </components>
   </files>
   <launchers>
         <file path="../../resources/images/JalviewLogo_Huge.png" />
       </iconImageFiles>
     </launcher>
+    <launcher name="Jalview package" id="1876" customizedId="" external="false" excludeFromMenu="false" unixMode="755" unixAutoStart="true" menuName="${compiler:sys.shortName} $$VERSION$$" icnsFile="" customMacBundleIdentifier="false" macBundleIdentifier="" swtApp="false" fileset="1873" macBundleBinary="JavaApplicationStub" addMacEntitlements="false" macEntitlementsFile="" useCustomMacosExecutableName="false" customMacosExecutableName="" useJavaMinVersionOverride="false" javaMinVersionOverride="" useJavaMaxVersionOverride="false" javaMaxVersionOverride="" checkUpdater="false" updateExecutionMode="unattendedProgress" unattendedUpdateTitle="${i18n:updater.WindowTitle(&quot;${compiler:sys.fullName}&quot;)}">
+      <executable name="${compiler:sys.shortName}" type="1" iconSet="true" iconFile="" executableDir="" redirectStderr="false" stderrFile="error.log" stderrMode="overwrite" redirectStdout="false" stdoutFile="output.log" stdoutMode="overwrite" failOnStderrOutput="false" executableMode="1" changeWorkingDirectory="false" workingDirectory="." singleInstance="true" serviceStartType="2" serviceDependencies="" serviceDescription="" jreLocation="" executionLevel="asInvoker" checkConsoleParameter="false" globalSingleInstance="false" singleInstanceActivate="true" dpiAware="java9+">
+        <versionInfo include="false" fileVersion="" fileDescription="" legalCopyright="" internalName="" productName="" />
+      </executable>
+      <splashScreen show="false" width="0" height="0" bitmapFile="" textOverlay="false">
+        <text>
+          <statusLine x="20" y="20" text="" fontSize="8" fontColor="0,0,0" bold="false" />
+          <versionLine x="20" y="40" text="version ${compiler:sys.version}" fontSize="8" fontColor="0,0,0" bold="false" />
+        </text>
+      </splashScreen>
+      <java mainClass="jalview.bin.Launcher" mainMode="1" vmParameters="" arguments="" allowVMPassthroughParameters="true" preferredVM="" bundleRuntime="true">
+        <classPath>
+          <scanDirectory location="dist" failOnError="false" />
+        </classPath>
+        <modulePath />
+        <nativeLibraryDirectories />
+        <vmOptions />
+      </java>
+      <includedFiles />
+      <unextractableFiles />
+      <vmOptionsFile mode="template" overwriteMode="0" fileMode="644">
+        <content />
+      </vmOptionsFile>
+      <customScript mode="1" file="">
+        <content />
+      </customScript>
+      <infoPlist mode="1" file="">
+        <content />
+      </infoPlist>
+      <iconImageFiles>
+        <file path="../../resources/images/JalviewLogo_Huge.png" />
+      </iconImageFiles>
+    </launcher>
   </launchers>
   <installerGui installerType="1" addOnAppId="" suggestPreviousLocations="true" autoUpdateDescriptorUrl="https://www.jalview.org/install4j/updates.xml" useAutoUpdateBaseUrl="false" autoUpdateBaseUrl="">
     <staticMembers script="" />
@@ -700,6 +761,36 @@ return console.askOkCancel(message, true);
             <preActivation />
             <postActivation />
             <actions>
+              <action name="" id="2012" customizedId="" beanClass="com.install4j.runtime.beans.actions.desktop.CreateStartMenuEntryAction" enabled="true" commentSet="false" comment="" actionElevationType="elevated" rollbackBarrier="false" rollbackBarrierExitCode="0" multiExec="false" failureStrategy="1" errorMessage="">
+                <serializedBean>
+                  <java class="java.beans.XMLDecoder">
+                    <object class="com.install4j.runtime.beans.actions.desktop.CreateStartMenuEntryAction">
+                      <void property="allUsers">
+                        <boolean>false</boolean>
+                      </void>
+                      <void property="entryName">
+                        <string>${compiler:sys.shortName}</string>
+                      </void>
+                      <void property="file">
+                        <object class="java.io.File">
+                          <string>${compiler:sys.shortName}</string>
+                        </object>
+                      </void>
+                      <void property="icon">
+                        <object class="com.install4j.api.beans.ExternalFile">
+                          <string>../../resources/images/jalview_logos.ico</string>
+                        </object>
+                      </void>
+                      <void property="unixIconFile">
+                        <object class="com.install4j.api.beans.ExternalFile">
+                          <string>../../resources/images/JalviewLogo_Huge.png</string>
+                        </object>
+                      </void>
+                    </object>
+                  </java>
+                </serializedBean>
+                <condition>!context.getBooleanVariable("sys.programGroupDisabled")</condition>
+              </action>
               <action name="" id="573" customizedId="" beanClass="com.install4j.runtime.beans.actions.desktop.CreateDesktopLinkAction" enabled="true" commentSet="false" comment="" actionElevationType="elevated" rollbackBarrier="false" rollbackBarrierExitCode="0" multiExec="false" failureStrategy="1" errorMessage="Could not make desktop link">
                 <serializedBean>
                   <java class="java.beans.XMLDecoder">
@@ -1666,20 +1757,24 @@ return console.askYesNo(message, true);
     </styles>
   </installerGui>
   <mediaSets>
-    <linuxDeb name="Linux Deb Archive" id="153" customizedId="" mediaFileName="" installDir="/opt/${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" overwriteNeverAsConfigFiles="false" dependencies="" bzip="true" description="Jalview Desktop" maintainerEmail="help@jalview.org" architectureSet="false" architecture="">
+    <linuxDeb name="Jalview .deb Package" id="153" customizedId="" mediaFileName="jalview-$$VERSION$$" installDir="/opt/${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" overwriteNeverAsConfigFiles="false" dependencies="openjdk-8-jre" bzip="true" description="Jalview Desktop" maintainerEmail="help@jalview.org" architectureSet="false" architecture="">
       <excludedComponents>
+        <component id="1031" />
         <component id="1155" />
         <component id="1156" />
         <component id="1276" />
+        <component id="2110" />
       </excludedComponents>
       <includedDownloadableComponents />
       <excludedLaunchers>
+        <launcher id="737" />
         <launcher id="1402" />
       </excludedLaunchers>
       <excludedBeans />
       <overriddenPrincipalLanguage id="en" customLocalizationFile="" />
       <exclude>
         <entry location=".i4j_fileset_" fileType="regular" />
+        <entry location=".i4j_fileset_734" fileType="regular" />
         <entry location=".i4j_fileset_880" fileType="regular" />
         <entry location=".i4j_fileset_882" fileType="regular" />
       </exclude>
@@ -1701,20 +1796,24 @@ return console.askYesNo(message, true);
         <content />
       </postUninstallScript>
     </linuxDeb>
-    <linuxRPM name="Linux RPM" id="570" customizedId="" mediaFileName="" installDir="/opt/${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" overwriteNeverAsConfigFiles="false" dependencies="" os="linux" arch="i386">
+    <linuxRPM name="Jalview RPM Package" id="570" customizedId="" mediaFileName="jalview-$$VERSION$$" installDir="/opt/${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" overwriteNeverAsConfigFiles="false" dependencies="java-1.8.0-openjdk" os="linux" arch="noarch">
       <excludedComponents>
+        <component id="1031" />
         <component id="1155" />
         <component id="1156" />
         <component id="1276" />
+        <component id="2110" />
       </excludedComponents>
       <includedDownloadableComponents />
       <excludedLaunchers>
+        <launcher id="737" />
         <launcher id="1402" />
       </excludedLaunchers>
       <excludedBeans />
       <overriddenPrincipalLanguage id="en" customLocalizationFile="" />
       <exclude>
         <entry location=".i4j_fileset_" fileType="regular" />
+        <entry location=".i4j_fileset_734" fileType="regular" />
         <entry location=".i4j_fileset_880" fileType="regular" />
         <entry location=".i4j_fileset_882" fileType="regular" />
       </exclude>
@@ -1736,11 +1835,13 @@ return console.askYesNo(message, true);
         <content />
       </postUninstallScript>
     </linuxRPM>
-    <windows name="Offline Windows" id="743" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="64" runPostProcessor="true" postProcessor="${compiler:JSIGN_SH} $EXECUTABLE" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="false" includedJRE="$$WINDOWS_JAVA_VM_TGZ$$" manualJREEntry="true" bundleType="1" jreURL="" jreShared="false" directDownload="false" installOnlyIfNecessary="false" customInstallBaseDir="~/AppData/Local" contentFilesType="1" verifyIntegrity="true">
+    <windows name="Offline Windows x64 Installer" id="743" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="64" runPostProcessor="true" postProcessor="${compiler:JSIGN_SH} $EXECUTABLE" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="false" includedJRE="$$WINDOWS_JAVA_VM_TGZ$$" manualJREEntry="true" bundleType="1" jreURL="" jreShared="false" directDownload="false" installOnlyIfNecessary="false" customInstallBaseDir="~/AppData/Local" contentFilesType="1" verifyIntegrity="true">
       <excludedComponents>
         <component id="1155" />
         <component id="1156" />
         <component id="1276" />
+        <component id="1881" />
+        <component id="2110" />
       </excludedComponents>
       <includedDownloadableComponents />
       <excludedLaunchers>
@@ -1751,6 +1852,31 @@ return console.askYesNo(message, true);
       <exclude>
         <entry location=".i4j_fileset_" fileType="regular" />
         <entry location=".i4j_fileset_880" fileType="regular" />
+        <entry location=".i4j_fileset_882" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
+      </exclude>
+      <variables />
+      <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
+        <commentFiles />
+        <customAttributes />
+      </autoUpdate>
+    </windows>
+    <windows name="Network Windows x64 Installer" id="1862" customizedId="" mediaFileName="${compiler:sys.shortName}-NETWORK_${compiler:sys.platform}_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="64" runPostProcessor="true" postProcessor="${compiler:JSIGN_SH} $EXECUTABLE" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="false" includedJRE="$$WINDOWS_JAVA_VM_TGZ$$" manualJREEntry="true" bundleType="1" jreURL="" jreShared="false" directDownload="false" installOnlyIfNecessary="false" customInstallBaseDir="~/AppData/Local" contentFilesType="1" verifyIntegrity="true">
+      <excludedComponents>
+        <component id="1031" />
+        <component id="1155" />
+        <component id="1156" />
+        <component id="1881" />
+        <component id="2110" />
+      </excludedComponents>
+      <includedDownloadableComponents />
+      <excludedLaunchers />
+      <excludedBeans />
+      <overriddenPrincipalLanguage id="en" customLocalizationFile="" />
+      <exclude>
+        <entry location=".i4j_fileset_734" fileType="regular" />
+        <entry location=".i4j_fileset_880" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
       </exclude>
       <variables />
       <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
@@ -1758,10 +1884,11 @@ return console.askYesNo(message, true);
         <customAttributes />
       </autoUpdate>
     </windows>
-    <macosArchive name="Offline macOS Single Bundle Archive" id="878" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}-app_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" archiveType="dmg" volumeName="${compiler:sys.shortName} Installer" launcherId="737">
+    <macosArchive name="Offline macOS Disk Image" id="878" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}-app_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" archiveType="dmg" volumeName="${compiler:sys.shortName} Installer" launcherId="737">
       <excludedComponents>
         <component id="1156" />
         <component id="1276" />
+        <component id="1881" />
       </excludedComponents>
       <includedDownloadableComponents />
       <excludedBeans />
@@ -1769,6 +1896,7 @@ return console.askYesNo(message, true);
       <exclude>
         <entry location=".i4j_fileset_" fileType="regular" />
         <entry location=".i4j_fileset_882" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
       </exclude>
       <variables />
       <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
@@ -1782,12 +1910,14 @@ return console.askYesNo(message, true);
         <symlink name="Jalview.app/Contents/Resources/app/${compiler:JRE_DIR}/Contents/MacOS/libjli.dylib" target="../Home/lib/jli/libjli.dylib" />
         <file name="Jalview.app/Contents/Resources/Jalview-File.icns" file="./Jalview-File.icns" />
         <file name="Jalview.app/Contents/Resources/Jalview-Version-Locator.icns" file="Jalview-Version-Locator.icns" />
+        <symlink name="Uninstall Old Jalview (optional).app" target="Jalview.app/Contents/Resources/app/Uninstall Old Jalview.app" />
       </topLevelFiles>
     </macosArchive>
-    <macosArchive name="Network macOS Single Bundle Archive" id="1274" customizedId="" mediaFileName="${compiler:sys.shortName}-NETWORK_${compiler:sys.platform}-app_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" archiveType="dmg" volumeName="${compiler:sys.shortName} Installer" launcherId="1402">
+    <macosArchive name="Network macOS Disk Image" id="1274" customizedId="" mediaFileName="${compiler:sys.shortName}-NETWORK_${compiler:sys.platform}-app_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false" archiveType="dmg" volumeName="${compiler:sys.shortName} Installer" launcherId="1402">
       <excludedComponents>
         <component id="1031" />
         <component id="1156" />
+        <component id="1881" />
       </excludedComponents>
       <includedDownloadableComponents />
       <excludedBeans />
@@ -1795,6 +1925,7 @@ return console.askYesNo(message, true);
       <exclude>
         <entry location=".i4j_fileset_734" fileType="regular" />
         <entry location=".i4j_fileset_882" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
       </exclude>
       <variables />
       <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
@@ -1808,10 +1939,17 @@ return console.askYesNo(message, true);
         <symlink name="Jalview.app/Contents/Resources/app/${compiler:JRE_DIR}/Contents/MacOS/libjli.dylib" target="../Home/lib/jli/libjli.dylib" />
         <file name="Jalview.app/Contents/Resources/Jalview-Version-Locator.icns" file="Jalview-Version-Locator.icns" />
         <file name="Jalview.app/Contents/Resources/Jalview-File.icns" file="Jalview-File.icns" />
+        <symlink name="Uninstall Old Jalview (optional).app" target="Jalview.app/Contents/Resources/app/Uninstall Old Jalview.app" />
       </topLevelFiles>
     </macosArchive>
-    <unixInstaller name="Unix Installer" id="1595" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}_installer_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="false" includedJRE="" manualJREEntry="false" bundleType="1" jreURL="" jreShared="false" directDownload="false" installOnlyIfNecessary="false" customInstallBaseDir="" contentFilesType="1">
-      <excludedComponents />
+    <unixInstaller name="Offline Unix Shell Installer" id="1595" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}_installer_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="false" includedJRE="" manualJREEntry="false" bundleType="1" jreURL="" jreShared="false" directDownload="false" installOnlyIfNecessary="false" customInstallBaseDir="~/opt/" contentFilesType="1">
+      <excludedComponents>
+        <component id="1155" />
+        <component id="1156" />
+        <component id="1276" />
+        <component id="1881" />
+        <component id="2110" />
+      </excludedComponents>
       <includedDownloadableComponents />
       <excludedLaunchers>
         <launcher id="1402" />
@@ -1819,9 +1957,10 @@ return console.askYesNo(message, true);
       <excludedBeans />
       <overriddenPrincipalLanguage id="en" customLocalizationFile="" />
       <exclude>
-        <entry location=".i4j_fileset_734" fileType="regular" />
+        <entry location=".i4j_fileset_" fileType="regular" />
         <entry location=".i4j_fileset_880" fileType="regular" />
         <entry location=".i4j_fileset_882" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
       </exclude>
       <variables />
       <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
@@ -1832,11 +1971,40 @@ return console.askYesNo(message, true);
         <content />
       </installerScript>
     </unixInstaller>
-    <unixArchive name="Unix Archive" id="1596" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}_archive_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false">
+    <unixInstaller name="Network Unix Shell Installer" id="1867" customizedId="" mediaFileName="${compiler:sys.shortName}-NETWORK_${compiler:sys.platform}_installer_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="false" includedJRE="" manualJREEntry="false" bundleType="1" jreURL="" jreShared="false" directDownload="false" installOnlyIfNecessary="false" customInstallBaseDir="~/opt/" contentFilesType="1">
       <excludedComponents>
         <component id="1031" />
         <component id="1155" />
         <component id="1156" />
+        <component id="1881" />
+        <component id="2110" />
+      </excludedComponents>
+      <includedDownloadableComponents />
+      <excludedLaunchers />
+      <excludedBeans />
+      <overriddenPrincipalLanguage id="en" customLocalizationFile="" />
+      <exclude>
+        <entry location=".i4j_fileset_734" fileType="regular" />
+        <entry location=".i4j_fileset_880" fileType="regular" />
+        <entry location=".i4j_fileset_882" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
+      </exclude>
+      <variables />
+      <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
+        <commentFiles />
+        <customAttributes />
+      </autoUpdate>
+      <installerScript mode="1" file="">
+        <content />
+      </installerScript>
+    </unixInstaller>
+    <unixArchive name="Offline Unix .tar.gz Archive" id="1596" customizedId="" mediaFileName="${compiler:sys.shortName}-OFFLINE_${compiler:sys.platform}_archive_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false">
+      <excludedComponents>
+        <component id="1155" />
+        <component id="1156" />
+        <component id="1276" />
+        <component id="1881" />
+        <component id="2110" />
       </excludedComponents>
       <includedDownloadableComponents />
       <excludedLaunchers>
@@ -1844,18 +2012,25 @@ return console.askYesNo(message, true);
       </excludedLaunchers>
       <excludedBeans />
       <overriddenPrincipalLanguage id="en" customLocalizationFile="" />
-      <exclude />
+      <exclude>
+        <entry location=".i4j_fileset_" fileType="regular" />
+        <entry location=".i4j_fileset_880" fileType="regular" />
+        <entry location=".i4j_fileset_882" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
+      </exclude>
       <variables />
       <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
         <commentFiles />
         <customAttributes />
       </autoUpdate>
     </unixArchive>
-    <windows name="Network Windows" id="1862" customizedId="" mediaFileName="${compiler:sys.shortName}-NETWORK_${compiler:sys.platform}_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="64" runPostProcessor="true" postProcessor="${compiler:JSIGN_SH} $EXECUTABLE" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="false" includedJRE="$$WINDOWS_JAVA_VM_TGZ$$" manualJREEntry="true" bundleType="1" jreURL="" jreShared="false" directDownload="false" installOnlyIfNecessary="false" customInstallBaseDir="~/AppData/Local" contentFilesType="1" verifyIntegrity="true">
+    <unixArchive name="Network Unix .tar.gz Archive" id="1871" customizedId="" mediaFileName="${compiler:sys.shortName}-NETWORK_${compiler:sys.platform}_archive_${compiler:sys.version}-j$$JAVA_INTEGER_VERSION$$" installDir="${compiler:sys.shortName}" overridePrincipalLanguage="false" jreBitType="all" runPostProcessor="false" postProcessor="" failOnPostProcessorError="false" useLegacyMediaFileIds="false" legacyMediaFileIds="" downloadURL="" includeAllDownloadableComponents="true" includedJRE="" manualJREEntry="false">
       <excludedComponents>
         <component id="1031" />
         <component id="1155" />
         <component id="1156" />
+        <component id="1881" />
+        <component id="2110" />
       </excludedComponents>
       <includedDownloadableComponents />
       <excludedLaunchers />
@@ -1864,13 +2039,15 @@ return console.askYesNo(message, true);
       <exclude>
         <entry location=".i4j_fileset_734" fileType="regular" />
         <entry location=".i4j_fileset_880" fileType="regular" />
+        <entry location=".i4j_fileset_882" fileType="regular" />
+        <entry location=".i4j_fileset_1873" fileType="regular" />
       </exclude>
       <variables />
       <autoUpdate useMinUpdatableVersion="false" minUpdatableVersion="" useMaxUpdatableVersion="false" maxUpdatableVersion="">
         <commentFiles />
         <customAttributes />
       </autoUpdate>
-    </windows>
+    </unixArchive>
   </mediaSets>
   <buildIds buildAll="true">
     <mediaSet refId="153" />
@@ -1881,6 +2058,8 @@ return console.askYesNo(message, true);
     <mediaSet refId="1595" />
     <mediaSet refId="1596" />
     <mediaSet refId="1862" />
+    <mediaSet refId="1867" />
+    <mediaSet refId="1871" />
   </buildIds>
   <buildOptions verbose="false" faster="false" disableSigning="false" disableJreBundling="false" debug="false" />
 </install4j>
diff --git a/utils/install4j/uninstall_app_dmg_file_inclusions.sh b/utils/install4j/uninstall_app_dmg_file_inclusions.sh
new file mode 100644 (file)
index 0000000..f5bed50
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+find Uninstall\ Old\ Jalview.app | perl -p -e 'chomp;$_=qq(            <file name=").$_.qq(" file="./).$_.qq(" />\n);' > uninstall_old_jalview_files.xml
+
+# makes the file used to replace the line
+# <file name="UNINSTALL_OLD_JALVIEW_APP_REPLACED_IN_GRADLE" file="./Uninstall Old Jalview.app" />
+# (replacement happens in gradle)
diff --git a/utils/install4j/uninstall_old_jalview.icns b/utils/install4j/uninstall_old_jalview.icns
new file mode 100644 (file)
index 0000000..67a2cbd
Binary files /dev/null and b/utils/install4j/uninstall_old_jalview.icns differ
diff --git a/utils/install4j/uninstall_old_jalview_files.xml b/utils/install4j/uninstall_old_jalview_files.xml
new file mode 100644 (file)
index 0000000..342fd90
--- /dev/null
@@ -0,0 +1,13 @@
+            <file name="Uninstall Old Jalview.app" file="./Uninstall Old Jalview.app" />
+            <file name="Uninstall Old Jalview.app/Contents" file="./Uninstall Old Jalview.app/Contents" />
+            <file name="Uninstall Old Jalview.app/Contents/MacOS" file="./Uninstall Old Jalview.app/Contents/MacOS" />
+            <file name="Uninstall Old Jalview.app/Contents/MacOS/applet" file="./Uninstall Old Jalview.app/Contents/MacOS/applet" />
+            <file name="Uninstall Old Jalview.app/Contents/Resources" file="./Uninstall Old Jalview.app/Contents/Resources" />
+            <file name="Uninstall Old Jalview.app/Contents/Resources/applet.rsrc" file="./Uninstall Old Jalview.app/Contents/Resources/applet.rsrc" />
+            <file name="Uninstall Old Jalview.app/Contents/Resources/description.rtfd" file="./Uninstall Old Jalview.app/Contents/Resources/description.rtfd" />
+            <file name="Uninstall Old Jalview.app/Contents/Resources/description.rtfd/TXT.rtf" file="./Uninstall Old Jalview.app/Contents/Resources/description.rtfd/TXT.rtf" />
+            <file name="Uninstall Old Jalview.app/Contents/Resources/Scripts" file="./Uninstall Old Jalview.app/Contents/Resources/Scripts" />
+            <file name="Uninstall Old Jalview.app/Contents/Resources/Scripts/main.scpt" file="./Uninstall Old Jalview.app/Contents/Resources/Scripts/main.scpt" />
+            <file name="Uninstall Old Jalview.app/Contents/Resources/applet.icns" file="./Uninstall Old Jalview.app/Contents/Resources/applet.icns" />
+            <file name="Uninstall Old Jalview.app/Contents/Info.plist" file="./Uninstall Old Jalview.app/Contents/Info.plist" />
+            <file name="Uninstall Old Jalview.app/Contents/PkgInfo" file="./Uninstall Old Jalview.app/Contents/PkgInfo" />