JAL-1588 restoring saved Chimera session(s)
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 26 Jan 2015 16:42:56 +0000 (16:42 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 26 Jan 2015 16:42:56 +0000 (16:42 +0000)
src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java
src/jalview/datamodel/PDBEntry.java
src/jalview/datamodel/ViewerData.java [new file with mode: 0644]
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AppJmol.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/StructureViewer.java

index b45404e..2c40e1c 100644 (file)
@@ -29,12 +29,6 @@ public class ChimeraManager
 {
   private static final boolean debug = false;
 
-  /*
-   * true: use REST API (recommended), false: use stdout/stdin (deprecated)
-   */
-  // TODO remove once definitely happy with using REST
-  private static final boolean USE_REST = true;
-
   private int chimeraRestPort;
 
   private Process chimera;
@@ -224,10 +218,14 @@ public class ChimeraManager
                     modelNumbers[0], modelNumbers[1]);
             currentModelsMap.put(modelNumber, newModel);
             models.add(newModel);
+
+            //
             // patch for Jalview - set model name in Chimera
+            //
             sendChimeraCommand("setattr M name " + modelName + " #"
                     + modelNumbers[0], false);
             // end patch for Jalview
+
             modelNumbers = null;
           }
         }
@@ -370,15 +368,7 @@ public class ChimeraManager
   {
     chimera = null;
     currentModelsMap.clear();
-    if (USE_REST)
-    {
       this.chimeraRestPort = 0;
-    }
-    else
-    {
-      chimeraListenerThread.requestStop();
-      chimeraListenerThread = null;
-    }
     structureManager.clearOnChimeraExit();
   }
 
@@ -549,13 +539,11 @@ public class ChimeraManager
         List<String> args = new ArrayList<String>();
         args.add(chimeraPath);
         args.add("--start");
-        args.add(USE_REST ? "RESTServer" : "ReadStdin");
+        args.add("RESTServer");
         ProcessBuilder pb = new ProcessBuilder(args);
         chimera = pb.start();
         error = "";
         workingPath = chimeraPath;
-        logger.info("Starting " + chimeraPath + " with "
-                + (USE_REST ? "REST API" : "stdin/stdout"));
         break;
       } catch (Exception e)
       {
@@ -566,18 +554,9 @@ public class ChimeraManager
     // If no error, then Chimera was launched successfully
     if (error.length() == 0)
     {
-      if (USE_REST)
-      {
-        this.chimeraRestPort = getPortNumber();
-        System.out.println("Chimera REST API on port " + chimeraRestPort);
-      }
-      else
-      {
-        // Initialize the listener threads
-        chimeraListenerThread = new ListenerThreads(chimera,
-                structureManager);
-        chimeraListenerThread.start();
-      }
+      this.chimeraRestPort = getPortNumber();
+      System.out.println("Chimera REST API started on port "
+              + chimeraRestPort);
       // structureManager.initChimTable();
       structureManager.setChimeraPathProperty(workingPath);
       // TODO: [Optional] Check Chimera version and show a warning if below 1.8
@@ -766,22 +745,17 @@ public class ChimeraManager
       } catch (InterruptedException q)
       {
       }
-      ;
     }
     busy = true;
     long startTime = System.currentTimeMillis();
     try
     {
-      if (USE_REST)
-      {
-        return sendRestCommand(command);
-      }
-      else
-      {
-        return sendStdinCommand(command, reply);
-      }
+      return sendRestCommand(command);
     } finally
     {
+      /*
+       * Make sure busy flag is reset come what may!
+       */
       busy = false;
       if (debug)
       {
index ee2b549..1cf9cd7 100755 (executable)
@@ -20,7 +20,7 @@
  */
 package jalview.datamodel;
 
-import java.util.*;
+import java.util.Hashtable;
 
 public class PDBEntry
 {
@@ -37,6 +37,7 @@ public class PDBEntry
    * 
    * @see java.lang.Object#equals(java.lang.Object)
    */
+  @Override
   public boolean equals(Object obj)
   {
     if (obj == null || !(obj instanceof PDBEntry))
@@ -44,7 +45,9 @@ public class PDBEntry
       return false;
     }
     if (obj == this)
+    {
       return true;
+    }
     PDBEntry o = (PDBEntry) obj;
     return (file == o.file || (file != null && o.file != null && o.file
             .equals(file)))
@@ -57,10 +60,29 @@ public class PDBEntry
                       .equals(o.properties)));
   }
 
+  /**
+   * Default constructor
+   */
   public PDBEntry()
   {
   }
 
+  /**
+   * Constructor given file path and PDB id.
+   * 
+   * @param filePath
+   */
+  public PDBEntry(String filePath, String pdbId)
+  {
+    this.file = filePath;
+    this.id = pdbId;
+  }
+  
+  /**
+   * Copy constructor.
+   * 
+   * @param entry
+   */
   public PDBEntry(PDBEntry entry)
   {
     file = entry.file;
diff --git a/src/jalview/datamodel/ViewerData.java b/src/jalview/datamodel/ViewerData.java
new file mode 100644 (file)
index 0000000..0b6b8d1
--- /dev/null
@@ -0,0 +1,189 @@
+package jalview.datamodel;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A data bean to hold stored data about a structure viewer.
+ */
+public class ViewerData
+{
+  private int x;
+
+  private int y;
+
+  private int width;
+
+  private int height;
+
+  private boolean alignWithPanel;
+
+  private boolean colourWithAlignPanel;
+
+  private boolean colourByViewer;
+
+  private String stateData = "";
+
+  private Map<File, StructureData> fileData = new HashMap<File, StructureData>();
+
+  public class StructureData
+  {
+    private String filePath;
+
+    private String pdbId;
+
+    private List<SequenceI> seqList;
+
+    // TODO and possibly a list of chains?
+
+    /**
+     * Constructor given structure file path and id.
+     * 
+     * @param pdbFile
+     * @param id
+     */
+    public StructureData(String pdbFile, String id)
+    {
+      this.filePath = pdbFile;
+      this.pdbId = id;
+      this.seqList = new ArrayList<SequenceI>();
+    }
+
+    public String getFilePath()
+    {
+      return filePath;
+    }
+
+    protected void setFilePath(String filePath)
+    {
+      this.filePath = filePath;
+    }
+
+    public String getPdbId()
+    {
+      return pdbId;
+    }
+
+    protected void setPdbId(String pdbId)
+    {
+      this.pdbId = pdbId;
+    }
+
+    public List<SequenceI> getSeqList()
+    {
+      return seqList;
+    }
+
+    protected void setSeqList(List<SequenceI> seqList)
+    {
+      this.seqList = seqList;
+    }
+  }
+
+  public ViewerData(int x, int y, int width, int height,
+          boolean alignWithPanel, boolean colourWithAlignPanel,
+          boolean colourByViewer)
+  {
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.alignWithPanel = alignWithPanel;
+    this.colourWithAlignPanel = colourWithAlignPanel;
+    this.colourByViewer = colourByViewer;
+  }
+
+  public int getX()
+  {
+    return x;
+  }
+
+  protected void setX(int x)
+  {
+    this.x = x;
+  }
+
+  public int getY()
+  {
+    return y;
+  }
+
+  protected void setY(int y)
+  {
+    this.y = y;
+  }
+
+  public int getWidth()
+  {
+    return width;
+  }
+
+  protected void setWidth(int width)
+  {
+    this.width = width;
+  }
+
+  public int getHeight()
+  {
+    return height;
+  }
+
+  public void setHeight(int height)
+  {
+    this.height = height;
+  }
+
+  public boolean isAlignWithPanel()
+  {
+    return alignWithPanel;
+  }
+
+  public void setAlignWithPanel(boolean alignWithPanel)
+  {
+    this.alignWithPanel = alignWithPanel;
+  }
+
+  public boolean isColourWithAlignPanel()
+  {
+    return colourWithAlignPanel;
+  }
+
+  public void setColourWithAlignPanel(boolean colourWithAlignPanel)
+  {
+    this.colourWithAlignPanel = colourWithAlignPanel;
+  }
+
+  public boolean isColourByViewer()
+  {
+    return colourByViewer;
+  }
+
+  public void setColourByViewer(boolean colourByViewer)
+  {
+    this.colourByViewer = colourByViewer;
+  }
+
+  public String getStateData()
+  {
+    return stateData;
+  }
+
+  public void setStateData(String stateData)
+  {
+    this.stateData = stateData;
+  }
+
+  public Map<File, StructureData> getFileData()
+  {
+    return fileData;
+  }
+
+  protected void setFileData(Map<File, StructureData> fileData)
+  {
+    this.fileData = fileData;
+  }
+
+}
index 6e6f5ee..b345c5e 100644 (file)
@@ -28,7 +28,6 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
-import jalview.io.AppletFormatAdapter;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.StructureMapping;
@@ -39,7 +38,6 @@ import jalview.util.Comparison;
 import jalview.util.MessageManager;
 
 import java.awt.Color;
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -65,123 +63,106 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
 
   private ChimeraManager viewer;
 
-  /**
+  /*
    * set if chimera state is being restored from some source - instructs binding
    * not to apply default display style when structure set is updated for first
    * time.
    */
   private boolean loadingFromArchive = false;
 
-  /**
-   * second flag to indicate if the Chimera viewer should ignore sequence
-   * colouring events from the structure manager because the GUI is still
-   * setting up
+  /*
+   * flag to indicate if the Chimera viewer should ignore sequence colouring
+   * events from the structure manager because the GUI is still setting up
    */
   private boolean loadingFinished = true;
 
-  /**
+  /*
    * state flag used to check if the Chimera viewer's paint method can be called
    */
   private boolean finishedInit = false;
 
-  public boolean isFinishedInit()
-  {
-    return finishedInit;
-  }
-
-  public void setFinishedInit(boolean finishedInit)
-  {
-    this.finishedInit = finishedInit;
-  }
-
-  boolean allChainsSelected = false;
-
-  /**
-   * when true, try to search the associated datamodel for sequences that are
-   * associated with any unknown structures in the Chimera view.
-   */
-  private boolean associateNewStructs = false;
+  private List<String> atomsPicked = new ArrayList<String>();
 
-  List<String> atomsPicked = new ArrayList<String>();
-
-  public List<String> chainNames;
+  private List<String> chainNames;
 
   private Map<String, String> chainFile;
 
-  StringBuffer eval = new StringBuffer();
+  private StringBuffer eval = new StringBuffer();
 
   public String fileLoadingError;
 
-  private Map<String, List<ChimeraModel>> chimmaps = new LinkedHashMap<String, List<ChimeraModel>>();
-
-  private List<String> mdlToFile = new ArrayList<String>();
+  /*
+   * Map of ChimeraModel objects keyed by PDB full local file name
+   */
+  private Map<String, List<ChimeraModel>> chimeraMaps = new LinkedHashMap<String, List<ChimeraModel>>();
 
-  /**
+  /*
    * the default or current model displayed if the model cannot be identified
    * from the selection message
    */
-  int frameNo = 0;
+  private int frameNo = 0;
 
-  String lastCommand;
+  private String lastCommand;
 
-  String lastMessage;
+  private String lastMessage;
 
-  boolean loadedInline;
+  private boolean loadedInline;
 
+  /**
+   * Open a PDB structure file in Chimera and set up mappings from Jalview.
+   * 
+   * We check if the PDB model id is already loaded in Chimera, if so don't
+   * reopen it. This is the case if Chimera has opened a saved session file.
+   * 
+   * @param pe
+   * @return
+   */
   public boolean openFile(PDBEntry pe)
   {
     String file = pe.getFile();
     try
     {
+      List<ChimeraModel> modelsToMap = new ArrayList<ChimeraModel>();
       List<ChimeraModel> oldList = viewer.getModelList();
-      viewer.openModel(file, pe.getId(), ModelType.PDB_MODEL);
-      List<ChimeraModel> newList = viewer.getModelList();
-      if (oldList.size() < newList.size())
+      boolean alreadyOpen = false;
+
+      /*
+       * If Chimera already has this model, don't reopen it, but do remap it.
+       */
+      for (ChimeraModel open : oldList)
       {
-        while (oldList.size() > 0)
+        if (open.getModelName().equals(pe.getId()))
         {
-          oldList.remove(0);
-          newList.remove(0);
-        }
-        chimmaps.put(file, newList);
-        for (ChimeraModel cm : newList)
-        {
-          while (mdlToFile.size() < 1 + cm.getModelNumber())
-          {
-            mdlToFile.add(new String(""));
-          }
-          mdlToFile.set(cm.getModelNumber(), file);
+          alreadyOpen = true;
+          modelsToMap.add(open);
         }
+      }
 
-        File fl = new File(file);
-        String protocol = AppletFormatAdapter.URL;
-        try
-        {
-          if (fl.exists())
-          {
-            protocol = AppletFormatAdapter.FILE;
-          }
-        } catch (Exception e)
-        {
-        } catch (Error e)
-        {
-        }
-        // Explicitly map to the filename used by Chimera ;
-        // pdbentry[pe].getFile(), protocol);
+      /*
+       * If Chimera doesn't yet have this model, ask it to open it, and retrieve
+       * the model names added by Chimera.
+       */
+      if (!alreadyOpen)
+      {
+        viewer.openModel(file, pe.getId(), ModelType.PDB_MODEL);
+        modelsToMap = viewer.getModelList();
+        modelsToMap.removeAll(oldList);
+      }
+
+      chimeraMaps.put(file, modelsToMap);
 
-        if (getSsm() != null)
+      if (getSsm() != null)
+      {
+        getSsm().addStructureViewerListener(this);
+        // ssm.addSelectionListener(this);
+        FeatureRenderer fr = getFeatureRenderer(null);
+        if (fr != null)
         {
-          getSsm().addStructureViewerListener(this);
-          // ssm.addSelectionListener(this);
-          FeatureRenderer fr = getFeatureRenderer(null);
-          if (fr != null)
-          {
-            fr.featuresAdded();
-          }
-          refreshGUI();
+          fr.featuresAdded();
         }
-        return true;
+        refreshGUI();
       }
+      return true;
     } catch (Exception q)
     {
       log("Exception when trying to open model " + file + "\n"
@@ -642,7 +623,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   {
     if (!viewer.isChimeraLaunched())
     {
-      viewer.launchChimera(csm.getChimeraPaths());
+      viewer.launchChimera(StructureManager.getChimeraPaths());
     }
     if (!viewer.isChimeraLaunched())
     {
@@ -662,7 +643,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
-   * Send a command to Chimera, and optionally log any responses.
+   * Send a command to Chimera, launching it first if necessary, and optionally
+   * log any responses.
    * 
    * @param command
    * @param logResponse
@@ -673,28 +655,12 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     checkLaunched();
     if (lastCommand == null || !lastCommand.equals(command))
     {
-//      Thread t = new Thread(new Runnable()
-//      {
-//        @Override
-//        public void run()
-//        {
       // trim command or it may never find a match in the replyLog!!
       lastReply = viewer.sendChimeraCommand(command.trim(), logResponse);
       if (debug && logResponse)
-          {
-            log("Response from command ('" + command + "') was:\n"
-                    + lastReply);
-          }
-//        }
-//      });
-      // TODO - use j7/8 thread management
-//      try
-//      {
-//        t.join();
-//      } catch (InterruptedException foo)
-//      {
-//      }
-//      ;
+      {
+        log("Response from command ('" + command + "') was:\n" + lastReply);
+      }
     }
     viewerCommandHistory(true);
     lastCommand = command;
@@ -853,8 +819,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     // // System.arraycopy(mset, 0, modelFileNames, 0, j);
     // }
 
-    return chimmaps.keySet().toArray(
-            modelFileNames = new String[chimmaps.size()]);
+    return chimeraMaps.keySet().toArray(
+            modelFileNames = new String[chimeraMaps.size()]);
   }
 
   /**
@@ -881,7 +847,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   public void highlightAtom(int atomIndex, int pdbResNum, String chain,
           String pdbfile)
   {
-    List<ChimeraModel> cms = chimmaps.get(pdbfile);
+    List<ChimeraModel> cms = chimeraMaps.get(pdbfile);
     if (cms != null)
     {
       int mdlNum = cms.get(0).getModelNumber();
@@ -1306,4 +1272,19 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     return true;
   }
 
+  public boolean isFinishedInit()
+  {
+    return finishedInit;
+  }
+
+  public void setFinishedInit(boolean finishedInit)
+  {
+    this.finishedInit = finishedInit;
+  }
+
+  public List<String> getChainNames()
+  {
+    return chainNames;
+  }
+
 }
index bd4a393..a4fe27c 100644 (file)
@@ -147,9 +147,7 @@ public class AppJmol extends StructureViewerBase
     PDBEntry[] pdbentrys = new PDBEntry[files.length];
     for (int i = 0; i < pdbentrys.length; i++)
     {
-      PDBEntry pdbentry = new PDBEntry();
-      pdbentry.setFile(files[i]);
-      pdbentry.setId(ids[i]);
+      PDBEntry pdbentry = new PDBEntry(files[i], ids[i]);
       pdbentrys[i] = pdbentry;
     }
     // / TODO: check if protocol is needed to be set, and if chains are
@@ -169,7 +167,7 @@ public class AppJmol extends StructureViewerBase
       seqColour.setSelected(false);
       viewerColour.setSelected(true);
     }
-    if (usetoColour)
+    else if (usetoColour)
     {
       useAlignmentPanelForColourbyseq(ap);
       jmb.setColourBySequence(true);
index 4e313b5..8ebd231 100644 (file)
@@ -27,7 +27,6 @@ import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
-import jalview.gui.Jalview2XML.ViewerData;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
@@ -99,9 +98,11 @@ public class ChimeraViewFrame extends StructureViewerBase
   private Thread worker = null;
 
   /*
-   * Path to Chimera session file - set in saveSession()
+   * Path to Chimera session file. This is set when an open Jalview/Chimera
+   * session is saved, or on restore from a Jalview project (if it holds the
+   * filename of any saved Chimera sessions).
    */
-  private String chimeraSessionFile = "";
+  private String chimeraSessionFile = null;
 
   /**
    * Initialise menu options.
@@ -311,12 +312,11 @@ public class ChimeraViewFrame extends StructureViewerBase
     jmb.setColourBySequence(true);
     setSize(400, 400); // probably should be a configurable/dynamic default here
     initMenus();
-    worker = null;
-    {
-      addingStructures = false;
-      worker = new Thread(this);
-      worker.start();
-    }
+
+    addingStructures = false;
+    worker = new Thread(this);
+    worker.start();
+
     this.addInternalFrameListener(new InternalFrameAdapter()
     {
       public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
@@ -343,20 +343,37 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   /**
-   * Create a new viewer from saved session state data.
+   * Create a new viewer from saved session state data including Chimera session
+   * file.
+   * 
+   * @param chimeraSession
    * 
-   * @param viewerData
-   * @param af
+   * @param alignPanel
+   * @param pdbArray
+   * @param seqsArray
+   * @param colourByChimera
+   * @param colourBySequence
    */
-  public ChimeraViewFrame(ViewerData viewerData, AlignFrame af)
+  public ChimeraViewFrame(String chimeraSession, AlignmentPanel alignPanel,
+          PDBEntry[] pdbArray,
+          SequenceI[][] seqsArray, boolean colourByChimera,
+          boolean colourBySequence)
   {
     super();
-    String chimeraSessionFile = viewerData.stateData;
-    openNewChimera(af.alignPanel, new PDBEntry[]
-    {}, new SequenceI[][]
-    {});
-    initChimera("open " + chimeraSessionFile);
-    // TODO restore mappings
+    this.chimeraSessionFile = chimeraSession;
+    openNewChimera(alignPanel, pdbArray, seqsArray);
+    if (colourByChimera)
+    {
+      jmb.setColourBySequence(false);
+      seqColour.setSelected(false);
+      viewerColour.setSelected(true);
+    }
+    else if (colourBySequence)
+    {
+      jmb.setColourBySequence(true);
+      seqColour.setSelected(true);
+      viewerColour.setSelected(false);
+    }
   }
 
   /**
@@ -433,18 +450,31 @@ public class ChimeraViewFrame extends StructureViewerBase
     return result;
   }
 
-  void initChimera(String command)
+  /**
+   * Launch Chimera. If we have a chimera session file name, send Chimera the
+   * command to open its saved session file.
+   */
+  void initChimera()
   {
     jmb.setFinishedInit(false);
-    // TODO: consider waiting until the structure/view is fully loaded before
-    // displaying
     jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true),
             getBounds().width, getBounds().height);
-    if (command == null)
+
+    /*
+     * Pass an empty 'command' to launch Chimera
+     */
+    jmb.evalStateCommand("", false);
+
+    if (this.chimeraSessionFile != null)
     {
-      command = "";
+      boolean opened = jmb.openSession(chimeraSessionFile);
+      if (!opened)
+      {
+        System.err
+                .println("An error occurred opening Chimera session file "
+                        + chimeraSessionFile);
+      }
     }
-    jmb.evalStateCommand(command, false);
     jmb.setFinishedInit(true);
   }
 
@@ -625,7 +655,7 @@ public class ChimeraViewFrame extends StructureViewerBase
       {
         try
         {
-          initChimera("");
+          initChimera();
         } catch (Exception ex)
         {
           Cache.log.error("Couldn't open Chimera viewer!", ex);
@@ -986,7 +1016,7 @@ public class ChimeraViewFrame extends StructureViewerBase
       repaint();
       return;
     }
-    setChainMenuItems(jmb.chainNames);
+    setChainMenuItems(jmb.getChainNames());
 
     this.setTitle(jmb.getViewerTitle("Chimera", true));
     if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1)
index bb4ef8b..728d2fc 100644 (file)
@@ -27,6 +27,8 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
+import jalview.datamodel.ViewerData;
+import jalview.datamodel.ViewerData.StructureData;
 import jalview.schemabinding.version2.AlcodMap;
 import jalview.schemabinding.version2.Alcodon;
 import jalview.schemabinding.version2.AlcodonFrame;
@@ -100,6 +102,7 @@ import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -128,47 +131,6 @@ import org.exolab.castor.xml.Unmarshaller;
  */
 public class Jalview2XML
 {
-
-  /**
-   * A data bean to hold stored data about a structure viewer.
-   */
-  public class ViewerData
-  {
-
-    private int x;
-
-    private int y;
-
-    private int width;
-
-    private int height;
-
-    public boolean alignWithPanel;
-
-    public boolean colourWithAlignPanel;
-
-    public boolean colourByViewer;
-
-    String stateData = "";
-
-    // todo: java bean in place of Object []
-    private Map<File, Object[]> fileData = new HashMap<File, Object[]>();
-
-    public ViewerData(int x, int y, int width, int height,
-            boolean alignWithPanel, boolean colourWithAlignPanel,
-            boolean colourByViewer)
-    {
-      this.x = x;
-      this.y = y;
-      this.width = width;
-      this.height = height;
-      this.alignWithPanel = alignWithPanel;
-      this.colourWithAlignPanel = colourWithAlignPanel;
-      this.colourByViewer = colourByViewer;
-    }
-
-  }
-
   /*
    * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
    * of sequence objects are created.
@@ -3073,9 +3035,11 @@ public class Jalview2XML
   protected void loadStructures(jarInputStreamProvider jprovider,
           JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
   {
-    // run through all PDB ids on the alignment, and collect mappings between
-    // jmol view ids and all sequences referring to it
-    Map<String, ViewerData> jmolViewIds = new HashMap<String, ViewerData>();
+    /*
+     * Run through all PDB ids on the alignment, and collect mappings between
+     * distinct view ids and all sequences referring to that view.
+     */
+    Map<String, ViewerData> structureViewers = new LinkedHashMap<String, ViewerData>();
 
     for (int i = 0; i < jseqs.length; i++)
     {
@@ -3115,9 +3079,9 @@ public class Jalview2XML
               sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
                       + "," + height;
             }
-            if (!jmolViewIds.containsKey(sviewid))
+            if (!structureViewers.containsKey(sviewid))
             {
-              jmolViewIds.put(sviewid, new ViewerData(x, y, width, height,
+              structureViewers.put(sviewid, new ViewerData(x, y, width, height,
                       false, false, true));
               // Legacy pre-2.7 conversion JAL-823 :
               // do not assume any view has to be linked for colour by
@@ -3128,44 +3092,53 @@ public class Jalview2XML
             // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
             // seqs_file 2}, boolean[] {
             // linkAlignPanel,superposeWithAlignpanel}} from hash
-            ViewerData jmoldat = jmolViewIds.get(sviewid);
-            jmoldat.alignWithPanel |= structureState
-                    .hasAlignwithAlignPanel() ? structureState.getAlignwithAlignPanel() : false;
-            // never colour by linked panel if not specified
-            jmoldat.colourWithAlignPanel |= structureState
-                    .hasColourwithAlignPanel() ? structureState.getColourwithAlignPanel()
-                    : false;
-            // default for pre-2.7 projects is that Jmol colouring is enabled
-            jmoldat.colourByViewer &= structureState
+            ViewerData jmoldat = structureViewers.get(sviewid);
+            jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
+                    | (structureState.hasAlignwithAlignPanel() ? structureState
+                            .getAlignwithAlignPanel() : false));
+
+            /*
+             * Default colour by linked panel to false if not specified (e.g.
+             * for pre-2.7 projects)
+             */
+            boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
+            colourWithAlignPanel |= (structureState
+                    .hasColourwithAlignPanel() ? structureState
+                    .getColourwithAlignPanel() : false);
+            jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
+
+            /*
+             * Default colour by viewer to true if not specified (e.g. for
+             * pre-2.7 projects)
+             */
+            boolean colourByViewer = jmoldat.isColourByViewer();
+            colourByViewer &= structureState
                     .hasColourByJmol() ? structureState
                     .getColourByJmol() : true;
+            jmoldat.setColourByViewer(colourByViewer);
 
-            if (jmoldat.stateData.length() < structureState.getContent()
-                    .length())
+            if (jmoldat.getStateData().length() < structureState
+                    .getContent().length())
             {
               {
-                jmoldat.stateData = structureState.getContent();
+                jmoldat.setStateData(structureState.getContent());
               }
             }
             if (ids[p].getFile() != null)
             {
               File mapkey = new File(ids[p].getFile());
-              Object[] seqstrmaps = jmoldat.fileData.get(mapkey);
+              StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
               if (seqstrmaps == null)
               {
-                jmoldat.fileData.put(mapkey,
-                        seqstrmaps = new Object[]
-                        { pdbFile, ids[p].getId(), new Vector(),
-                            new Vector() });
+                jmoldat.getFileData().put(
+                        mapkey,
+                        seqstrmaps = jmoldat.new StructureData(pdbFile,
+                                ids[p].getId()));
               }
-              if (!((Vector) seqstrmaps[2]).contains(seq))
+              if (!seqstrmaps.getSeqList().contains(seq))
               {
-                ((Vector) seqstrmaps[2]).addElement(seq);
-                // ((Vector)seqstrmaps[3]).addElement(n) :
-                // in principle, chains
-                // should be stored here : do we need to
-                // TODO: store and recover seq/pdb_id :
-                // chain mappings
+                seqstrmaps.getSeqList().add(seq);
+                // TODO and chains?
               }
             }
             else
@@ -3178,7 +3151,7 @@ public class Jalview2XML
       }
     }
       // Instantiate the associated structure views
-      for (Entry<String, ViewerData> entry : jmolViewIds.entrySet())
+      for (Entry<String, ViewerData> entry : structureViewers.entrySet())
       {
         createOrLinkStructureViewer(entry, af, ap);
       }
@@ -3212,7 +3185,7 @@ public class Jalview2XML
      * Pending an XML element for ViewerType, just check if stateData contains
      * "chimera" (part of the chimera session filename).
      */
-    if (svattrib.stateData.indexOf("chimera") > -1)
+    if (svattrib.getStateData().indexOf("chimera") > -1)
     {
       createChimeraViewer(viewerData, af);
     }
@@ -3232,36 +3205,34 @@ public class Jalview2XML
           AlignFrame af)
   {
     final ViewerData data = viewerData.getValue();
-    String chimeraSession = data.stateData;
-    List<String> pdbfilenames = new ArrayList<String>();
-    List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
-    List<String> pdbids = new ArrayList<String>();
+    String chimeraSession = data.getStateData();
 
     if (new File(chimeraSession).exists())
     {
-      Set<Entry<File, Object[]>> fileData = data.fileData.entrySet();
+      Set<Entry<File, StructureData>> fileData = data.getFileData()
+              .entrySet();
       List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
       List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
-      for (Entry<File, Object[]> pdb : fileData)
-      {
-        String filePath = (String) pdb.getValue()[0];
-        String pdbId = (String) pdb.getValue()[1];
-        final Vector seqList = (Vector) pdb.getValue()[2];
-        PDBEntry pdbentry = new PDBEntry();
-        pdbentry.setFile(filePath);
-        pdbentry.setId(pdbId);
-        pdbs.add(pdbentry);
-        SequenceI[] seqs = new SequenceI[seqList.size()];
-        seqList.copyInto(seqs);
+      for (Entry<File, StructureData> pdb : fileData)
+      {
+        String filePath = pdb.getValue().getFilePath();
+        String pdbId = pdb.getValue().getPdbId();
+        pdbs.add(new PDBEntry(filePath, pdbId));
+        final List<SequenceI> seqList = pdb.getValue().getSeqList();
+        SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
         allseqs.add(seqs);
       }
 
+      boolean colourByChimera = data.isColourByViewer();
+      boolean colourBySequence = data.isColourWithAlignPanel();
+
       // TODO can/should this be done via StructureViewer (like Jmol)?
       final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs
               .size()]);
       final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs.size()][]);
-      ChimeraViewFrame cvf = // new ChimeraViewFrame(data, af);
-      new ChimeraViewFrame(af.alignPanel, pdbArray, seqsArray);
+      new ChimeraViewFrame(chimeraSession, af.alignPanel, pdbArray,
+              seqsArray,
+              colourByChimera, colourBySequence);
     }
     else
     {
@@ -3282,13 +3253,13 @@ public class Jalview2XML
           final Entry<String, ViewerData> viewerData, AlignFrame af)
   {
     final ViewerData svattrib = viewerData.getValue();
-    String state = svattrib.stateData;
+    String state = svattrib.getStateData();
     List<String> pdbfilenames = new ArrayList<String>();
     List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
     List<String> pdbids = new ArrayList<String>();
     StringBuilder newFileLoc = new StringBuilder(64);
     int cp = 0, ncp, ecp;
-    Map<File, Object[]> oldFiles = svattrib.fileData;
+    Map<File, StructureData> oldFiles = svattrib.getFileData();
     while ((ncp = state.indexOf("load ", cp)) > -1)
     {
       do
@@ -3302,11 +3273,11 @@ public class Jalview2XML
         // have to normalize filename - since Jmol and jalview do
         // filename
         // translation differently.
-        Object[] filedat = oldFiles.get(new File(oldfilenam));
-        newFileLoc.append(Platform.escapeString((String) filedat[0]));
-        pdbfilenames.add((String) filedat[0]);
-        pdbids.add((String) filedat[1]);
-        seqmaps.add(((Vector<SequenceI>) filedat[2])
+        StructureData filedat = oldFiles.get(new File(oldfilenam));
+        newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
+        pdbfilenames.add(filedat.getFilePath());
+        pdbids.add(filedat.getPdbId());
+        seqmaps.add(filedat.getSeqList()
                 .toArray(new SequenceI[0]));
         newFileLoc.append("\"");
         cp = ecp + 1; // advance beyond last \" and set cursor so we can
@@ -3327,15 +3298,14 @@ public class Jalview2XML
       {
         // add this and any other pdb files that should be present in
         // the viewer
-        Object[] filedat = oldFiles.get(id);
-        String nfilename;
-        newFileLoc.append(((String) filedat[0]));
-        pdbfilenames.add((String) filedat[0]);
-        pdbids.add((String) filedat[1]);
-        seqmaps.add(((Vector<SequenceI>) filedat[2])
+        StructureData filedat = oldFiles.get(id);
+        newFileLoc.append(filedat.getFilePath());
+        pdbfilenames.add(filedat.getFilePath());
+        pdbids.add(filedat.getPdbId());
+        seqmaps.add(filedat.getSeqList()
                 .toArray(new SequenceI[0]));
         newFileLoc.append(" \"");
-        newFileLoc.append((String) filedat[0]);
+        newFileLoc.append(filedat.getFilePath());
         newFileLoc.append("\"");
 
       }
@@ -3373,8 +3343,8 @@ public class Jalview2XML
       final String fileloc = newFileLoc.toString();
       final String sviewid = viewerData.getKey();
       final AlignFrame alf = af;
-      final java.awt.Rectangle rect = new java.awt.Rectangle(svattrib.x,
-              svattrib.y, svattrib.width, svattrib.height);
+      final Rectangle rect = new Rectangle(svattrib.getX(),
+              svattrib.getY(), svattrib.getWidth(), svattrib.getHeight());
       try
       {
         javax.swing.SwingUtilities.invokeAndWait(new Runnable()
@@ -3448,9 +3418,10 @@ public class Jalview2XML
         /*
          * Otherwise test for matching position and size of viewer frame
          */
-        else if (frame.getX() == svattrib.x && frame.getY() == svattrib.y
-                && frame.getHeight() == svattrib.height
-                && frame.getWidth() == svattrib.width)
+        else if (frame.getX() == svattrib.getX()
+                && frame.getY() == svattrib.getY()
+                && frame.getHeight() == svattrib.getHeight()
+                && frame.getWidth() == svattrib.getWidth())
         {
           comp = (AppJmol) frame;
           // todo: break?
@@ -3476,10 +3447,10 @@ public class Jalview2XML
     // NOTE: if the jalview project is part of a shared session then
     // view synchronization should/could be done here.
 
-    final boolean useinViewerSuperpos = svattrib.alignWithPanel;
-    final boolean usetoColourbyseq = svattrib.colourWithAlignPanel;
-    final boolean viewerColouring = svattrib.colourByViewer;
-    Map<File, Object[]> oldFiles = svattrib.fileData;
+    final boolean useinViewerSuperpos = svattrib.isAlignWithPanel();
+    final boolean usetoColourbyseq = svattrib.isColourWithAlignPanel();
+    final boolean viewerColouring = svattrib.isColourByViewer();
+    Map<File, StructureData> oldFiles = svattrib.getFileData();
 
     /*
      * Add mapping for sequences in this view to an already open viewer
@@ -3489,13 +3460,10 @@ public class Jalview2XML
     {
       // add this and any other pdb files that should be present in the
       // viewer
-      Object[] filedat = oldFiles.get(id);
-      String pdbFile = (String) filedat[0];
-      SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
-              .toArray(new SequenceI[0]);
-      binding
-              .getSsm()
-              .setMapping(seq, null, pdbFile,
+      StructureData filedat = oldFiles.get(id);
+      String pdbFile = filedat.getFilePath();
+      SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
+      binding.getSsm().setMapping(seq, null, pdbFile,
               jalview.io.AppletFormatAdapter.FILE);
       binding.addSequenceForStructFile(pdbFile, seq);
     }
index 7d986c8..b3b1962 100644 (file)
@@ -24,7 +24,7 @@ import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
-import jalview.gui.Jalview2XML.ViewerData;
+import jalview.datamodel.ViewerData;
 import jalview.structure.StructureSelectionManager;
 
 import java.awt.Rectangle;
@@ -135,16 +135,16 @@ public class StructureViewer
           AlignmentPanel alignPanel, ViewerData viewerData, String fileloc,
           Rectangle rect, String vid)
   {
-    final boolean useinViewerSuperpos = viewerData.alignWithPanel;
-    final boolean usetoColourbyseq = viewerData.colourWithAlignPanel;
-    final boolean viewerColouring = viewerData.colourByViewer;
+    final boolean useinViewerSuperpos = viewerData.isAlignWithPanel();
+    final boolean usetoColourbyseq = viewerData.isColourWithAlignPanel();
+    final boolean viewerColouring = viewerData.isColourByViewer();
 
     JalviewStructureDisplayI sview = null;
     switch (type)
     {
     case JMOL:
-      sview = new AppJmol(pdbf, id, sq, alignPanel, useinViewerSuperpos,
-              usetoColourbyseq, viewerColouring, fileloc, rect, vid);
+      sview = new AppJmol(pdbf, id, sq, alignPanel, usetoColourbyseq,
+              useinViewerSuperpos, viewerColouring, fileloc, rect, vid);
       break;
     case CHIMERA:
       Cache.log.error("Unsupported structure viewer type "