Merge branch 'develop' into features/JAL-2295setChimeraAttributes
[jalview.git] / src / jalview / gui / ChimeraViewFrame.java
index 1d60d6c..4c38898 100644 (file)
  */
 package jalview.gui;
 
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+import jalview.ext.rbvi.chimera.ChimeraCommands;
+import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
+import jalview.io.StructureFile;
+import jalview.schemes.BuriedColourScheme;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.HelixColourScheme;
+import jalview.schemes.HydrophobicColourScheme;
+import jalview.schemes.PurinePyrimidineColourScheme;
+import jalview.schemes.StrandColourScheme;
+import jalview.schemes.TaylorColourScheme;
+import jalview.schemes.TurnColourScheme;
+import jalview.schemes.ZappoColourScheme;
+import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.ws.dbsources.Pdb;
+
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
@@ -33,10 +62,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Random;
-import java.util.Set;
 import java.util.Vector;
 
 import javax.swing.JCheckBoxMenuItem;
@@ -50,31 +78,6 @@ import javax.swing.event.InternalFrameEvent;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
 
-import jalview.bin.Cache;
-import jalview.datamodel.Alignment;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceI;
-import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
-import jalview.gui.StructureViewer.ViewerType;
-import jalview.io.AppletFormatAdapter;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.ZappoColourScheme;
-import jalview.structures.models.AAStructureBindingModel;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-import jalview.ws.dbsources.Pdb;
-
 /**
  * GUI elements for handling an external chimera display
  * 
@@ -87,23 +90,9 @@ public class ChimeraViewFrame extends StructureViewerBase
 
   private boolean allChainsSelected = false;
 
-  private boolean alignAddedStructures = false;
-
-  /*
-   * state flag for PDB retrieval thread
-   */
-  private boolean _started = false;
-
-  private boolean addingStructures = false;
-
   private IProgressIndicator progressBar = null;
 
   /*
-   * pdb retrieval thread.
-   */
-  private Thread worker = null;
-
-  /*
    * 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).
@@ -170,8 +159,8 @@ public class ChimeraViewFrame extends StructureViewerBase
                 alignStructs.setToolTipText(MessageManager
                         .formatMessage(
                                 "label.align_structures_using_linked_alignment_views",
-                                new Object[]
-                                { new Integer(_alignwith.size()).toString() }));
+                                new Object[] { new Integer(_alignwith
+                                        .size()).toString() }));
               }
             });
     handler.itemStateChanged(null);
@@ -197,172 +186,137 @@ public class ChimeraViewFrame extends StructureViewerBase
         // TODO Auto-generated method stub
       }
     });
+
+    JMenuItem writeFeatures = new JMenuItem(
+            MessageManager.getString("label.create_chimera_attributes"));
+    writeFeatures.setToolTipText(MessageManager
+            .getString("label.create_chimera_attributes_tip"));
+    writeFeatures.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        sendFeaturesToChimera();
+      }
+    });
+    viewerActionMenu.add(writeFeatures);
+
+    final JMenu fetchAttributes = new JMenu("Fetch Chimera attributes");
+    fetchAttributes
+            .setToolTipText("Copy Chimera attribute to Jalview feature");
+    fetchAttributes.addMouseListener(new MouseAdapter()
+    {
+
+      @Override
+      public void mouseEntered(MouseEvent e)
+      {
+        buildAttributesMenu(fetchAttributes);
+      }
+    });
+    viewerActionMenu.add(fetchAttributes);
+
   }
 
   /**
-   * add a single PDB structure to a new or existing Chimera view
+   * Query Chimera for its residue attribute names and add them as items off the
+   * attributes menu
    * 
-   * @param pdbentry
-   * @param seq
-   * @param chains
-   * @param ap
+   * @param attributesMenu
    */
-  public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq,
-          String[] chains, final AlignmentPanel ap)
+  protected void buildAttributesMenu(JMenu attributesMenu)
   {
-    super();
-
-    /*
-     * is the pdb file already loaded?
-     */
-    String pdbId = pdbentry.getId();
-    String alreadyMapped = ap.getStructureSelectionManager()
-            .alreadyMappedToFile(pdbId);
-
-    if (alreadyMapped != null)
+    List<String> atts = jmb.sendChimeraCommand("list resattr", true);
+    if (atts == null)
     {
-      int option = chooseAddSequencesToViewer(pdbId);
-      if (option == JOptionPane.CANCEL_OPTION)
-      {
-        return;
-      }
-      if (option == JOptionPane.YES_OPTION)
-      {
-        addSequenceMappingsToStructure(seq, chains, ap, alreadyMapped);
-        return;
-      }
+      return;
     }
-
-    /*
-     * Check if there are other Chimera views involving this alignment and give
-     * user the option to add and align this molecule to one of them
-     */
-    List<ChimeraViewFrame> existingViews = getChimeraWindowsFor(ap);
-    for (ChimeraViewFrame view : existingViews)
+    attributesMenu.removeAll();
+    Collections.sort(atts);
+    for (String att : atts)
     {
-      // TODO: highlight view somehow
+      final String attName = att.split(" ")[1];
+
       /*
-       * JAL-1742 exclude view with this structure already mapped (don't offer
-       * to align chain B to chain A of the same structure)
+       * ignore 'jv_*' attributes, as these are Jalview features that have
+       * been transferred to residue attributes in Chimera!
        */
-      if (view.hasPdbId(pdbId))
+      if (!attName.startsWith(ChimeraCommands.NAMESPACE_PREFIX))
       {
-        continue;
-      }
-      int option = chooseAlignStructureToViewer(pdbId, view);
-      if (option == JOptionPane.CANCEL_OPTION)
-      {
-        return;
-      }
-      if (option == JOptionPane.YES_OPTION)
-      {
-        view.useAlignmentPanelForSuperposition(ap);
-        view.addStructure(pdbentry, seq, chains, true, ap.alignFrame);
-        return;
+        JMenuItem menuItem = new JMenuItem(attName);
+        menuItem.addActionListener(new ActionListener()
+        {
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            getChimeraAttributes(attName);
+          }
+        });
+        attributesMenu.add(menuItem);
       }
     }
-
-    /*
-     * If the options above are declined or do not apply, open a new viewer
-     */
-    openNewChimera(ap, new PDBEntry[]
-    { pdbentry }, new SequenceI[][]
-    { seq });
   }
 
   /**
-   * Presents a dialog with the option to add an align a structure to an
-   * existing Chimera view
+   * Read residues in Chimera with the given attribute name, and set as features
+   * on the corresponding sequence positions (if any)
    * 
-   * @param pdbId
-   * @param view
-   * @return YES, NO or CANCEL JOptionPane code
+   * @param attName
    */
-  protected int chooseAlignStructureToViewer(String pdbId,
-          ChimeraViewFrame view)
+  protected void getChimeraAttributes(String attName)
   {
-    int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
-            MessageManager.formatMessage("label.add_pdbentry_to_view",
-                    new Object[]
-                    { pdbId, view.getTitle() }), MessageManager
-                    .getString("label.align_to_existing_structure_view"),
-            JOptionPane.YES_NO_CANCEL_OPTION);
-    return option;
+    jmb.copyStructureAttributesToFeatures(attName, getAlignmentPanel());
   }
 
   /**
-   * Presents a dialog with the option to add sequences to a viewer which
-   * already has their structure open
-   * 
-   * @param pdbId
-   * @return YES, NO or CANCEL JOptionPane code
+   * Send a command to Chimera to create residue attributes for Jalview features
+   * <p>
+   * The syntax is: setattr r <attName> <attValue> <atomSpec>
+   * <p>
+   * For example: setattr r jv:chain "Ferredoxin-1, Chloroplastic" #0:94.A
    */
-  protected int chooseAddSequencesToViewer(String pdbId)
+  protected void sendFeaturesToChimera()
   {
-    int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
-            MessageManager.formatMessage(
-                    "label.pdb_entry_is_already_displayed", new Object[]
-                    { pdbId }), MessageManager.formatMessage(
-                    "label.map_sequences_to_visible_window", new Object[]
-                    { pdbId }), JOptionPane.YES_NO_CANCEL_OPTION);
-    return option;
+    jmb.sendFeaturesToViewer(getAlignmentPanel());
   }
 
   /**
-   * Adds mappings for the given sequences to an already opened PDB structure,
-   * and updates any viewers that have the PDB file
+   * add a single PDB structure to a new or existing Chimera view
    * 
+   * @param pdbentry
    * @param seq
    * @param chains
    * @param ap
-   * @param pdbFilename
    */
-  protected void addSequenceMappingsToStructure(SequenceI[] seq,
-          String[] chains, final AlignmentPanel ap, String pdbFilename)
+  public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq,
+          String[] chains, final AlignmentPanel ap)
   {
-    // TODO : Fix multiple seq to one chain issue here.
-    /*
-     * create the mappings
-     */
-    ap.getStructureSelectionManager().setMapping(seq, chains, pdbFilename,
-            AppletFormatAdapter.FILE);
+    this();
+    String pdbId = pdbentry.getId();
 
     /*
-     * alert the FeatureRenderer to show new (PDB RESNUM) features
+     * If the PDB file is already loaded, the user may just choose to add to an
+     * existing viewer (or cancel)
      */
-    if (ap.getSeqPanel().seqCanvas.fr != null)
+    if (addAlreadyLoadedFile(seq, chains, ap, pdbId))
     {
-      ap.getSeqPanel().seqCanvas.fr.featuresAdded();
-      ap.paintAlignment(true);
+      return;
     }
 
     /*
-     * add the sequences to any other Chimera viewers for this pdb file
+     * Check if there are other Chimera views involving this alignment and give
+     * user the option to add and align this molecule to one of them (or cancel)
      */
-    // JBPNOTE: this looks like a binding routine, rather than a gui routine
-    for (JInternalFrame frame : Desktop.instance.getAllFrames())
+    if (addToExistingViewer(pdbentry, seq, chains, ap, pdbId))
     {
-      if (frame instanceof ChimeraViewFrame)
-      {
-        ChimeraViewFrame chimeraView = ((ChimeraViewFrame) frame);
-        for (int pe = 0; pe < chimeraView.jmb.getPdbCount(); pe++)
-        {
-          if (chimeraView.jmb.getPdbEntry(pe).getFile().equals(pdbFilename))
-          {
-            chimeraView.jmb.addSequence(pe, seq);
-            chimeraView.addAlignmentPanel(ap);
-            /*
-             * add it to the set of alignments used for colouring structure by
-             * sequence
-             */
-            chimeraView.useAlignmentPanelForColourbyseq(ap);
-            chimeraView.buildActionMenu();
-            ap.getStructureSelectionManager().sequenceColoursChanged(ap);
-            break;
-          }
-        }
-      }
+      return;
     }
+
+    /*
+     * If the options above are declined or do not apply, show the structure in
+     * a new viewer
+     */
+    openNewChimera(ap, new PDBEntry[] { pdbentry },
+            new SequenceI[][] { seq });
   }
 
   /**
@@ -376,6 +330,10 @@ public class ChimeraViewFrame extends StructureViewerBase
     }
   }
 
+  /**
+   * Answers true if this viewer already involves the given PDB ID
+   */
+  @Override
   protected boolean hasPdbId(String pdbId)
   {
     return jmb.hasPdbId(pdbId);
@@ -385,10 +343,8 @@ public class ChimeraViewFrame extends StructureViewerBase
           SequenceI[][] seqs)
   {
     createProgressBar();
-    String[][] chains = extractChains(seqs);
     jmb = new JalviewChimeraBindingModel(this,
-            ap.getStructureSelectionManager(), pdbentrys, seqs, chains,
-            null);
+            ap.getStructureSelectionManager(), pdbentrys, seqs, null);
     addAlignmentPanel(ap);
     useAlignmentPanelForColourbyseq(ap);
     if (pdbentrys.length > 1)
@@ -406,6 +362,7 @@ public class ChimeraViewFrame extends StructureViewerBase
 
     this.addInternalFrameListener(new InternalFrameAdapter()
     {
+      @Override
       public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
       {
         closeViewer(false);
@@ -415,38 +372,6 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   /**
-   * Retrieve chains for sequences by inspecting their PDB refs. The hope is
-   * that the first will be to the sequence's own chain. Really need a more
-   * managed way of doing this.
-   * 
-   * @param seqs
-   * @return
-   */
-  protected String[][] extractChains(SequenceI[][] seqs)
-  {
-    String[][] chains = new String[seqs.length][];
-    for (int i = 0; i < seqs.length; i++)
-    {
-      chains[i] = new String[seqs[i].length];
-      int seqno = 0;
-      for (SequenceI seq : seqs[i])
-      {
-        String chain = null;
-        if (seq.getDatasetSequence() != null)
-        {
-          Vector<PDBEntry> pdbrefs = seq.getDatasetSequence().getAllPDBEntries();
-          if (pdbrefs != null && pdbrefs.size() > 0)
-          {
-            chain = pdbrefs.get(0).getChainCode();
-          }
-        }
-        chains[i][seqno++] = chain;
-      }
-    }
-    return chains;
-  }
-
-  /**
    * Create a new viewer from saved session state data including Chimera session
    * file
    * 
@@ -459,12 +384,11 @@ public class ChimeraViewFrame extends StructureViewerBase
    * @param newViewId
    */
   public ChimeraViewFrame(String chimeraSessionFile,
-          AlignmentPanel alignPanel,
-          PDBEntry[] pdbArray,
+          AlignmentPanel alignPanel, PDBEntry[] pdbArray,
           SequenceI[][] seqsArray, boolean colourByChimera,
           boolean colourBySequence, String newViewId)
   {
-    super();
+    this();
     setViewId(newViewId);
     this.chimeraSessionFile = chimeraSessionFile;
     openNewChimera(alignPanel, pdbArray, seqsArray);
@@ -493,101 +417,41 @@ public class ChimeraViewFrame extends StructureViewerBase
   public ChimeraViewFrame(PDBEntry[] pe, SequenceI[][] seqs,
           AlignmentPanel ap)
   {
-    super();
+    this();
     openNewChimera(ap, pe, seqs);
   }
 
-  public ChimeraViewFrame(Map<PDBEntry, List<SequenceI>> toView,
-          AlignmentPanel alignPanel)
+  /**
+   * Default constructor
+   */
+  public ChimeraViewFrame()
   {
     super();
 
     /*
-     * Convert the map of sequences per pdb entry into the tied arrays expected
-     * by openNewChimera
-     * 
-     * TODO pass the Map down to openNewChimera and its callees instead
+     * closeViewer will decide whether or not to close this frame
+     * depending on whether user chooses to Cancel or not
      */
-    final Set<PDBEntry> pdbEntries = toView.keySet();
-    PDBEntry[] pdbs = pdbEntries.toArray(new PDBEntry[pdbEntries.size()]);
-    SequenceI[][] seqsForPdbs = new SequenceI[pdbEntries.size()][];
-    for (int i = 0; i < pdbs.length; i++)
-    {
-      final List<SequenceI> seqsForPdb = toView.get(pdbs[i]);
-      seqsForPdbs[i] = seqsForPdb.toArray(new SequenceI[seqsForPdb.size()]);
-    }
-
-    openNewChimera(alignPanel, pdbs, seqsForPdbs);
+    setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE);
   }
 
   /**
-   * add a new structure (with associated sequences and chains) to this viewer,
-   * retrieving it if necessary first.
-   * 
-   * @param pdbentry
-   * @param seq
-   * @param chains
-   * @param alignFrame
-   * @param align
-   *          if true, new structure(s) will be align using associated alignment
+   * Returns a list of any Chimera viewers in the desktop. The list is
+   * restricted to those linked to the given alignment panel if it is not null.
    */
-  private void addStructure(final PDBEntry pdbentry, final SequenceI[] seq,
-          final String[] chains, final boolean b,
-          final IProgressIndicator alignFrame)
-  {
-    if (pdbentry.getFile() == null)
-    {
-      if (worker != null && worker.isAlive())
-      {
-        // a retrieval is in progress, wait around and add ourselves to the
-        // queue.
-        new Thread(new Runnable()
-        {
-          public void run()
-          {
-            while (worker != null && worker.isAlive() && _started)
-            {
-              try
-              {
-                Thread.sleep(100 + ((int) Math.random() * 100));
-
-              } catch (Exception e)
-              {
-              }
-
-            }
-            // and call ourselves again.
-            addStructure(pdbentry, seq, chains, b, alignFrame);
-          }
-        }).start();
-        return;
-      }
-    }
-    // otherwise, start adding the structure.
-    jmb.addSequenceAndChain(new PDBEntry[]
-    { pdbentry }, new SequenceI[][]
-    { seq }, new String[][]
-    { chains });
-    addingStructures = true;
-    _started = false;
-    alignAddedStructures = b;
-    // progressBar = alignFrame; // visual indication happens on caller frame.
-    (worker = new Thread(this)).start();
-    return;
-  }
-
-  private List<ChimeraViewFrame> getChimeraWindowsFor(AlignmentPanel apanel)
+  @Override
+  protected List<StructureViewerBase> getViewersFor(AlignmentPanel ap)
   {
-    List<ChimeraViewFrame> result = new ArrayList<ChimeraViewFrame>();
+    List<StructureViewerBase> result = new ArrayList<StructureViewerBase>();
     JInternalFrame[] frames = Desktop.instance.getAllFrames();
 
     for (JInternalFrame frame : frames)
     {
       if (frame instanceof ChimeraViewFrame)
       {
-        if (((StructureViewerBase) frame).isLinkedWith(apanel))
+        if (ap == null || ((StructureViewerBase) frame).isLinkedWith(ap))
         {
-          result.add((ChimeraViewFrame) frame);
+          result.add((StructureViewerBase) frame);
         }
       }
     }
@@ -600,18 +464,15 @@ public class ChimeraViewFrame extends StructureViewerBase
    */
   void initChimera()
   {
-    jmb.setFinishedInit(false);
-    jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true),
+    Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true),
             getBounds().width, getBounds().height);
 
     if (!jmb.launchChimera())
     {
-      JOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
+      JvOptionPane.showMessageDialog(Desktop.desktop,
               MessageManager.getString("label.chimera_failed"),
               MessageManager.getString("label.error_loading_file"),
-              JOptionPane.ERROR_MESSAGE);
+              JvOptionPane.ERROR_MESSAGE);
       this.dispose();
       return;
     }
@@ -626,7 +487,6 @@ public class ChimeraViewFrame extends StructureViewerBase
                         + chimeraSessionFile);
       }
     }
-    jmb.setFinishedInit(true);
 
     jmb.startChimeraListener();
   }
@@ -637,6 +497,7 @@ public class ChimeraViewFrame extends StructureViewerBase
    * 
    * @param chainNames
    */
+  @Override
   void setChainMenuItems(List<String> chainNames)
   {
     chainMenu.removeAll();
@@ -648,6 +509,7 @@ public class ChimeraViewFrame extends StructureViewerBase
             MessageManager.getString("label.all"));
     menuItem.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent evt)
       {
         allChainsSelected = true;
@@ -670,6 +532,7 @@ public class ChimeraViewFrame extends StructureViewerBase
       menuItem = new JCheckBoxMenuItem(chainName, true);
       menuItem.addItemListener(new ItemListener()
       {
+        @Override
         public void itemStateChanged(ItemEvent evt)
         {
           if (!allChainsSelected)
@@ -686,6 +549,7 @@ public class ChimeraViewFrame extends StructureViewerBase
   /**
    * Show only the selected chain(s) in the viewer
    */
+  @Override
   void showSelectedChains()
   {
     List<String> toshow = new ArrayList<String>();
@@ -711,20 +575,29 @@ public class ChimeraViewFrame extends StructureViewerBase
    * @param closeChimera
    *          if true, close any linked Chimera process; if false, prompt first
    */
+  @Override
   public void closeViewer(boolean closeChimera)
   {
-    if (jmb.isChimeraRunning())
+    if (jmb != null && jmb.isChimeraRunning())
     {
       if (!closeChimera)
       {
         String prompt = MessageManager.formatMessage(
-                "label.confirm_close_chimera", new Object[]
-                { jmb.getViewerTitle("Chimera", false) });
+                "label.confirm_close_chimera",
+                new Object[] { jmb.getViewerTitle("Chimera", false) });
         prompt = JvSwingUtils.wrapTooltip(true, prompt);
-        int confirm = JOptionPane.showConfirmDialog(this, prompt,
+        int confirm = JvOptionPane.showConfirmDialog(this, prompt,
                 MessageManager.getString("label.close_viewer"),
-                JOptionPane.YES_NO_OPTION);
-        closeChimera = confirm == JOptionPane.YES_OPTION;
+                JvOptionPane.YES_NO_CANCEL_OPTION);
+        /*
+         * abort closure if user hits escape or Cancel
+         */
+        if (confirm == JvOptionPane.CANCEL_OPTION
+                || confirm == JvOptionPane.CLOSED_OPTION)
+        {
+          return;
+        }
+        closeChimera = confirm == JvOptionPane.YES_OPTION;
       }
       jmb.closeViewer(closeChimera);
     }
@@ -735,12 +608,14 @@ public class ChimeraViewFrame extends StructureViewerBase
     // TODO: check for memory leaks where instance isn't finalised because jmb
     // holds a reference to the window
     jmb = null;
+    dispose();
   }
 
   /**
    * Open any newly added PDB structures in Chimera, having first fetched data
    * from PDB (if not already saved).
    */
+  @Override
   public void run()
   {
     _started = true;
@@ -750,6 +625,7 @@ public class ChimeraViewFrame extends StructureViewerBase
     List<PDBEntry> filePDB = new ArrayList<PDBEntry>();
     List<Integer> filePDBpos = new ArrayList<Integer>();
     PDBEntry thePdbEntry = null;
+    StructureFile pdb = null;
     try
     {
       String[] curfiles = jmb.getPdbFile(); // files currently in viewer
@@ -810,16 +686,16 @@ public class ChimeraViewFrame extends StructureViewerBase
     if (errormsgs.length() > 0)
     {
 
-      JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
               .formatMessage("label.pdb_entries_couldnt_be_retrieved",
-                      new Object[]
-                      { errormsgs.toString() }), MessageManager
-              .getString("label.couldnt_load_file"),
-              JOptionPane.ERROR_MESSAGE);
+                      new Object[] { errormsgs.toString() }),
+              MessageManager.getString("label.couldnt_load_file"),
+              JvOptionPane.ERROR_MESSAGE);
     }
 
     if (files.length() > 0)
     {
+      jmb.setFinishedInit(false);
       if (!addingStructures)
       {
         try
@@ -840,16 +716,17 @@ public class ChimeraViewFrame extends StructureViewerBase
           {
             int pos = filePDBpos.get(num).intValue();
             long startTime = startProgressBar("Chimera "
-                    + MessageManager.getString("status.opening_file"));
+                    + MessageManager.getString("status.opening_file_for")
+                    + " " + pe.getId());
             jmb.openFile(pe);
             jmb.addSequence(pos, jmb.getSequence()[pos]);
             File fl = new File(pe.getFile());
-            String protocol = AppletFormatAdapter.URL;
+            DataSourceType protocol = DataSourceType.URL;
             try
             {
               if (fl.exists())
               {
-                protocol = AppletFormatAdapter.FILE;
+                protocol = DataSourceType.FILE;
               }
             } catch (Throwable e)
             {
@@ -858,10 +735,9 @@ public class ChimeraViewFrame extends StructureViewerBase
               stopProgressBar("", startTime);
             }
             // Explicitly map to the filename used by Chimera ;
-            jmb.getSsm().setMapping(jmb.getSequence()[pos],
-                    jmb.getChains()[pos],
-                    pe.getFile(),
-                    protocol);
+            pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
+                    jmb.getChains()[pos], pe.getFile(), protocol);
+            stashFoundChains(pdb, pe.getFile());
           } catch (OutOfMemoryError oomerror)
           {
             new OOMWarning(
@@ -877,6 +753,8 @@ public class ChimeraViewFrame extends StructureViewerBase
           }
         }
       }
+
+      jmb.refreshGUI();
       jmb.setFinishedInit(true);
       jmb.setLoadingFromArchive(false);
 
@@ -886,10 +764,11 @@ public class ChimeraViewFrame extends StructureViewerBase
         jmb.updateColours(ap);
       }
       // do superposition if asked to
-      if (alignAddedStructures)
+      if (Cache.getDefault("AUTOSUPERIMPOSE", true) && alignAddedStructures)
       {
         new Thread(new Runnable()
         {
+          @Override
           public void run()
           {
             alignStructs_withAllAlignPanels();
@@ -911,8 +790,20 @@ public class ChimeraViewFrame extends StructureViewerBase
    * @return
    * @throws Exception
    */
+
+  private void stashFoundChains(StructureFile pdb, String file)
+  {
+    for (int i = 0; i < pdb.getChains().size(); i++)
+    {
+      String chid = new String(pdb.getId() + ":"
+              + pdb.getChains().elementAt(i).id);
+      jmb.getChainNames().add(chid);
+      jmb.getChainFile().put(chid, file);
+    }
+  }
   private String fetchPdbFile(PDBEntry processingEntry) throws Exception
   {
+    // FIXME: this is duplicated code with Jmol frame ?
     String filePath = null;
     Pdb pdbclient = new Pdb();
     AlignmentI pdbseq = null;
@@ -924,8 +815,7 @@ public class ChimeraViewFrame extends StructureViewerBase
      * Write 'fetching PDB' progress on AlignFrame as we are not yet visible
      */
     String msg = MessageManager.formatMessage("status.fetching_pdb",
-            new Object[]
-            { pdbid });
+            new Object[] { pdbid });
     getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
     // long hdl = startProgressBar(MessageManager.formatMessage(
     // "status.fetching_pdb", new Object[]
@@ -938,8 +828,7 @@ public class ChimeraViewFrame extends StructureViewerBase
       new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
     } finally
     {
-      msg = pdbid + " "
-              + MessageManager.getString("label.state_completed");
+      msg = pdbid + " " + MessageManager.getString("label.state_completed");
       getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
       // stopProgressBar(msg, hdl);
     }
@@ -1223,10 +1112,10 @@ public class ChimeraViewFrame extends StructureViewerBase
     setChainMenuItems(jmb.getChainNames());
 
     this.setTitle(jmb.getViewerTitle("Chimera", true));
-    if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1)
-    {
+    // if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1)
+    // {
       viewerActionMenu.setVisible(true);
-    }
+    // }
     if (!jmb.isLoadingFromArchive())
     {
       seqColour_actionPerformed(null);
@@ -1284,6 +1173,7 @@ public class ChimeraViewFrame extends StructureViewerBase
     }
   }
 
+  @Override
   public void setJalviewColourScheme(ColourSchemeI ucs)
   {
     jmb.setJalviewColourScheme(ucs);
@@ -1395,4 +1285,10 @@ public class ChimeraViewFrame extends StructureViewerBase
   {
     return ViewerType.CHIMERA;
   }
+
+  @Override
+  protected AAStructureBindingModel getBindingModel()
+  {
+    return jmb;
+  }
 }