Merge branch 'features/JAL-1333' into Release_2_8_2_Branch
[jalview.git] / src / jalview / gui / Jalview2XML.java
index da81945..f3bc42e 100644 (file)
@@ -1,19 +1,21 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
  * Copyright (C) 2014 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.
+ * 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/>.
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.gui;
@@ -30,6 +32,7 @@ import javax.swing.*;
 
 import org.exolab.castor.xml.*;
 
+import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
@@ -942,10 +945,10 @@ public class Jalview2XML
           }
           else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
           {
-            groups[i]
-                    .setColour(ColourSchemeProperty
-                            .getColourName(((jalview.schemes.AnnotationColourGradient) sg.cs)
-                                    .getBaseColour()));
+            groups[i].setColour("AnnotationColourGradient");
+            groups[i].setAnnotationColours(constructAnnotationColours(
+                    (jalview.schemes.AnnotationColourGradient) sg.cs,
+                    userColours, jms));
           }
           else if (sg.cs instanceof jalview.schemes.UserColourScheme)
           {
@@ -1018,28 +1021,11 @@ public class Jalview2XML
       }
       else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
       {
-        jalview.schemes.AnnotationColourGradient acg = (jalview.schemes.AnnotationColourGradient) av
-                .getGlobalColourScheme();
+        AnnotationColours ac = constructAnnotationColours(
+                (jalview.schemes.AnnotationColourGradient) av
+                        .getGlobalColourScheme(),
+                userColours, jms);
 
-        AnnotationColours ac = new AnnotationColours();
-        ac.setAboveThreshold(acg.getAboveThreshold());
-        ac.setThreshold(acg.getAnnotationThreshold());
-        ac.setAnnotation(acg.getAnnotation());
-        if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
-        {
-          ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
-                  userColours, jms));
-        }
-        else
-        {
-          ac.setColourScheme(ColourSchemeProperty.getColourName(acg
-                  .getBaseColour()));
-        }
-
-        ac.setMaxColour(acg.getMaxColour().getRGB());
-        ac.setMinColour(acg.getMinColour().getRGB());
-        ac.setPerSequence(acg.isSeqAssociated());
-        ac.setPredefinedColours(acg.isPredefinedColours());
         view.setAnnotationColours(ac);
         view.setBgColour("AnnotationColourGradient");
       }
@@ -1259,7 +1245,35 @@ public class Jalview2XML
     return object;
   }
 
-  private void storeAlignmentAnnotation(AlignmentAnnotation[] aa, IdentityHashMap groupRefs, AlignmentViewport av, Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
+  private AnnotationColours constructAnnotationColours(
+          AnnotationColourGradient acg, Vector userColours,
+          JalviewModelSequence jms)
+  {
+    AnnotationColours ac = new AnnotationColours();
+    ac.setAboveThreshold(acg.getAboveThreshold());
+    ac.setThreshold(acg.getAnnotationThreshold());
+    ac.setAnnotation(acg.getAnnotation());
+    if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
+    {
+      ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
+              userColours, jms));
+    }
+    else
+    {
+      ac.setColourScheme(ColourSchemeProperty.getColourName(acg
+              .getBaseColour()));
+    }
+
+    ac.setMaxColour(acg.getMaxColour().getRGB());
+    ac.setMinColour(acg.getMinColour().getRGB());
+    ac.setPerSequence(acg.isSeqAssociated());
+    ac.setPredefinedColours(acg.isPredefinedColours());
+    return ac;
+  }
+
+  private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
+          IdentityHashMap groupRefs, AlignmentViewport av,
+          Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
   {
 
     for (int i = 0; i < aa.length; i++)
@@ -1782,7 +1796,7 @@ public class Jalview2XML
     try
     {
       // create list to store references for any new Jmol viewers created
-      newStructureViewers = new Vector<AppJmol>();
+      newStructureViewers = new Vector<JalviewStructureDisplayI>();
       // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
       // Workaround is to make sure caller implements the JarInputStreamProvider
       // interface
@@ -1913,8 +1927,7 @@ public class Jalview2XML
             if (object.getJalviewModelSequence().getViewportCount() > 0)
             {
               af = _af;
-              if (object.getJalviewModelSequence().getViewportCount() > 1
-                      && af.viewport.gatherViewsHere)
+              if (af.viewport.gatherViewsHere)
               {
                 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
               }
@@ -2554,7 +2567,7 @@ public class Jalview2XML
     if (jms.getJGroupCount() > 0)
     {
       JGroup[] groups = jms.getJGroup();
-
+      boolean addAnnotSchemeGroup = false;
       for (int i = 0; i < groups.length; i++)
       {
         ColourSchemeI cs = null;
@@ -2565,6 +2578,12 @@ public class Jalview2XML
           {
             cs = GetUserColourScheme(jms, groups[i].getColour());
           }
+          else if (groups[i].getColour().equals("AnnotationColourGradient")
+                  && groups[i].getAnnotationColours() != null)
+          {
+            addAnnotSchemeGroup = true;
+            cs = null;
+          }
           else
           {
             cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
@@ -2663,7 +2682,12 @@ public class Jalview2XML
           }
         }
         al.addGroup(sg);
-
+        if (addAnnotSchemeGroup)
+        {
+          // reconstruct the annotation colourscheme
+          sg.cs = constructAnnotationColour(
+                  groups[i].getAnnotationColours(), null, al, jms, false);
+        }
       }
     }
     if (view == null)
@@ -2714,6 +2738,13 @@ public class Jalview2XML
 
       }
     }
+    /**
+     * indicate that annotation colours are applied across all groups (pre
+     * Jalview 2.8.1 behaviour)
+     */
+    boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
+            object.getVersion());
+
     AlignmentPanel ap = null;
     boolean isnewview = true;
     if (viewId != null)
@@ -3102,10 +3133,11 @@ public class Jalview2XML
                   @Override
                   public void run()
                   {
-                    AppJmol sview = null;
+                    JalviewStructureDisplayI sview = null;
                     try
                     {
-                      sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
+                      // JAL-1333 note - we probably can't migrate Jmol views to UCSF Chimera!
+                      sview = new StructureViewer(alf.alignPanel.getStructureSelectionManager()).createView(StructureViewer.Viewer.JMOL, pdbf, id, sq, alf.alignPanel,
                               useinJmolsuperpos, usetoColourbyseq,
                               jmolColouring, fileloc, rect, vid);
                       addNewStructureViewer(sview);
@@ -3178,12 +3210,70 @@ public class Jalview2XML
     // and finally return.
     return af;
   }
-  Vector<AppJmol> newStructureViewers=null;
-  protected void addNewStructureViewer(AppJmol sview)
+
+  /**
+   * 
+   * @param supported
+   *          - minimum version we are comparing against
+   * @param version
+   *          - version of data being processsed.
+   * @return true if version is development/null or evaluates to the same or
+   *         later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
+   */
+  private boolean isVersionStringLaterThan(String supported, String version)
+  {
+    if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
+            || version.equalsIgnoreCase("Test")
+            || version.equalsIgnoreCase("AUTOMATED BUILD"))
+    {
+      System.err.println("Assuming project file with "
+              + (version == null ? "null" : version)
+              + " is compatible with Jalview version " + supported);
+      return true;
+    }
+    else
+    {
+      StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
+              version, ".");
+      while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
+      {
+        // convert b to decimal to catch bugfix releases within a series
+        String curT = currentV.nextToken().toLowerCase().replace('b', '.');
+        String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
+        try
+        {
+          if (Float.valueOf(curT) > Float.valueOf(fileT))
+          {
+            // current version is newer than the version that wrote the file
+            return false;
+          }
+        } catch (NumberFormatException nfe)
+        {
+          System.err
+                  .println("** WARNING: Version comparison failed for tokens ("
+                          + curT
+                          + ") and ("
+                          + fileT
+                          + ")\n** Current: '"
+                          + supported + "' and Version: '" + version + "'");
+        }
+      }
+      if (currentV.hasMoreElements())
+      {
+        // fileV has no minor version but identical series to current
+        return false;
+      }
+    }
+    return true;
+  }
+
+  Vector<JalviewStructureDisplayI> newStructureViewers = null;
+
+  protected void addNewStructureViewer(JalviewStructureDisplayI sview)
   {
     if (newStructureViewers != null)
     {
-      sview.jmb.setFinishedLoadingFromArchive(false);
+      sview.getBinding().setFinishedLoadingFromArchive(false);
       newStructureViewers.add(sview);
     }
   }
@@ -3192,9 +3282,9 @@ public class Jalview2XML
   {
     if (newStructureViewers != null)
     {
-      for (AppJmol sview : newStructureViewers)
+      for (JalviewStructureDisplayI sview : newStructureViewers)
       {
-        sview.jmb.setFinishedLoadingFromArchive(true);
+        sview.getBinding().setFinishedLoadingFromArchive(true);
       }
       newStructureViewers.clear();
       newStructureViewers = null;
@@ -3314,111 +3404,11 @@ public class Jalview2XML
       }
       else if (view.getBgColour().startsWith("Annotation"))
       {
-        // int find annotation
-        if (af.viewport.getAlignment().getAlignmentAnnotation() != null)
-        {
-          for (int i = 0; i < af.viewport.getAlignment()
-                  .getAlignmentAnnotation().length; i++)
-          {
-            if (af.viewport.getAlignment().getAlignmentAnnotation()[i].label
-                    .equals(view.getAnnotationColours().getAnnotation()))
-            {
-              if (af.viewport.getAlignment().getAlignmentAnnotation()[i]
-                      .getThreshold() == null)
-              {
-                af.viewport.getAlignment().getAlignmentAnnotation()[i]
-                        .setThreshold(new jalview.datamodel.GraphLine(view
-                                .getAnnotationColours().getThreshold(),
-                                "Threshold", java.awt.Color.black)
+        AnnotationColours viewAnnColour = view.getAnnotationColours();
+        cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
 
-                        );
-              }
-
-              if (view.getAnnotationColours().getColourScheme()
-                      .equals("None"))
-              {
-                cs = new AnnotationColourGradient(af.viewport
-                        .getAlignment().getAlignmentAnnotation()[i],
-                        new java.awt.Color(view.getAnnotationColours()
-                                .getMinColour()), new java.awt.Color(view
-                                .getAnnotationColours().getMaxColour()),
-                        view.getAnnotationColours().getAboveThreshold());
-              }
-              else if (view.getAnnotationColours().getColourScheme()
-                      .startsWith("ucs"))
-              {
-                cs = new AnnotationColourGradient(af.viewport
-                        .getAlignment().getAlignmentAnnotation()[i],
-                        GetUserColourScheme(jms, view
-                                .getAnnotationColours().getColourScheme()),
-                        view.getAnnotationColours().getAboveThreshold());
-              }
-              else
-              {
-                cs = new AnnotationColourGradient(af.viewport
-                        .getAlignment().getAlignmentAnnotation()[i],
-                        ColourSchemeProperty.getColour(al, view
-                                .getAnnotationColours().getColourScheme()),
-                        view.getAnnotationColours().getAboveThreshold());
-              }
-              if (view.getAnnotationColours().hasPerSequence())
-              {
-                ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
-              }
-              if (view.getAnnotationColours().hasPredefinedColours())
-              {
-                ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
-              }
-              // Also use these settings for all the groups
-              if (al.getGroups() != null)
-              {
-                for (int g = 0; g < al.getGroups().size(); g++)
-                {
-                  jalview.datamodel.SequenceGroup sg = al.getGroups()
-                          .get(g);
+        // annpos
 
-                  if (sg.cs == null)
-                  {
-                    continue;
-                  }
-
-                  /*
-                   * if
-                   * (view.getAnnotationColours().getColourScheme().equals("None"
-                   * )) { sg.cs = new AnnotationColourGradient(
-                   * af.viewport.getAlignment().getAlignmentAnnotation()[i], new
-                   * java.awt.Color(view.getAnnotationColours().
-                   * getMinColour()), new
-                   * java.awt.Color(view.getAnnotationColours().
-                   * getMaxColour()),
-                   * view.getAnnotationColours().getAboveThreshold()); } else
-                   */
-                  {
-                    sg.cs = new AnnotationColourGradient(af.viewport
-                            .getAlignment().getAlignmentAnnotation()[i],
-                            sg.cs, view.getAnnotationColours()
-                                    .getAboveThreshold());
-                    if (cs instanceof AnnotationColourGradient) 
-                    {
-                      if (view.getAnnotationColours().hasPerSequence())
-                      { 
-                        ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
-                      }
-                      if (view.getAnnotationColours().hasPredefinedColours())
-                      {
-                        ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
-                      }
-                    }
-                  }
-
-                }
-              }
-
-              break;
-            }
-
-          }
-        }
       }
       else
       {
@@ -3612,6 +3602,131 @@ public class Jalview2XML
     return af;
   }
 
+  private ColourSchemeI constructAnnotationColour(
+          AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
+          JalviewModelSequence jms, boolean checkGroupAnnColour)
+  {
+    boolean propagateAnnColour = false;
+    ColourSchemeI cs = null;
+    AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
+    if (checkGroupAnnColour && al.getGroups() != null
+            && al.getGroups().size() > 0)
+    {
+      // pre 2.8.1 behaviour
+      // check to see if we should transfer annotation colours
+      propagateAnnColour = true;
+      for (jalview.datamodel.SequenceGroup sg : al.getGroups())
+      {
+        if (sg.cs instanceof AnnotationColourGradient)
+        {
+          propagateAnnColour = false;
+        }
+      }
+    }
+    // int find annotation
+    if (annAlignment.getAlignmentAnnotation() != null)
+    {
+      for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
+      {
+        if (annAlignment.getAlignmentAnnotation()[i].label
+                .equals(viewAnnColour.getAnnotation()))
+        {
+          if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
+          {
+            annAlignment.getAlignmentAnnotation()[i]
+                    .setThreshold(new jalview.datamodel.GraphLine(
+                            viewAnnColour.getThreshold(), "Threshold",
+                            java.awt.Color.black)
+
+                    );
+          }
+
+          if (viewAnnColour.getColourScheme().equals("None"))
+          {
+            cs = new AnnotationColourGradient(
+                    annAlignment.getAlignmentAnnotation()[i],
+                    new java.awt.Color(viewAnnColour.getMinColour()),
+                    new java.awt.Color(viewAnnColour.getMaxColour()),
+                    viewAnnColour.getAboveThreshold());
+          }
+          else if (viewAnnColour.getColourScheme().startsWith("ucs"))
+          {
+            cs = new AnnotationColourGradient(
+                    annAlignment.getAlignmentAnnotation()[i],
+                    GetUserColourScheme(jms,
+                            viewAnnColour.getColourScheme()),
+                    viewAnnColour.getAboveThreshold());
+          }
+          else
+          {
+            cs = new AnnotationColourGradient(
+                    annAlignment.getAlignmentAnnotation()[i],
+                    ColourSchemeProperty.getColour(al,
+                            viewAnnColour.getColourScheme()),
+                    viewAnnColour.getAboveThreshold());
+          }
+          if (viewAnnColour.hasPerSequence())
+          {
+            ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
+                    .isPerSequence());
+          }
+          if (viewAnnColour.hasPredefinedColours())
+          {
+            ((AnnotationColourGradient) cs)
+                    .setPredefinedColours(viewAnnColour
+                            .isPredefinedColours());
+          }
+          if (propagateAnnColour && al.getGroups() != null)
+          {
+            // Also use these settings for all the groups
+            for (int g = 0; g < al.getGroups().size(); g++)
+            {
+              jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
+
+              if (sg.cs == null)
+              {
+                continue;
+              }
+
+              /*
+               * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
+               * new AnnotationColourGradient(
+               * annAlignment.getAlignmentAnnotation()[i], new
+               * java.awt.Color(viewAnnColour. getMinColour()), new
+               * java.awt.Color(viewAnnColour. getMaxColour()),
+               * viewAnnColour.getAboveThreshold()); } else
+               */
+              {
+                sg.cs = new AnnotationColourGradient(
+                        annAlignment.getAlignmentAnnotation()[i], sg.cs,
+                        viewAnnColour.getAboveThreshold());
+                if (cs instanceof AnnotationColourGradient)
+                {
+                  if (viewAnnColour.hasPerSequence())
+                  {
+                    ((AnnotationColourGradient) cs)
+                            .setSeqAssociated(viewAnnColour.isPerSequence());
+                  }
+                  if (viewAnnColour.hasPredefinedColours())
+                  {
+                    ((AnnotationColourGradient) cs)
+                            .setPredefinedColours(viewAnnColour
+                                    .isPredefinedColours());
+                  }
+                }
+              }
+
+            }
+          }
+
+          break;
+        }
+
+      }
+    }
+    return cs;
+  }
+
   private void reorderAutoannotation(AlignFrame af, Alignment al,
           ArrayList<JvAnnotRow> autoAlan)
   {