JAL-1953 2.11.2 with Archeopteryx!
[jalview.git] / src / jalview / gui / ChimeraViewFrame.java
index 67eddca..e78938a 100644 (file)
  */
 package jalview.gui;
 
-import jalview.bin.Cache;
-import jalview.datamodel.AlignmentI;
-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.StructureFile;
-import jalview.structures.models.AAStructureBindingModel;
-import jalview.util.BrowserLauncher;
-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.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Random;
+import java.util.Map;
 
-import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
 
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.bin.Console;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.StructureViewerModel;
+import jalview.datamodel.StructureViewerModel.StructureData;
+import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
+import jalview.io.StructureFile;
+import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.ImageMaker.TYPE;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+
 /**
  * GUI elements for handling an external chimera display
  * 
@@ -65,8 +62,6 @@ public class ChimeraViewFrame extends StructureViewerBase
 {
   private JalviewChimeraBinding jmb;
 
-  private IProgressIndicator progressBar = 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
@@ -74,7 +69,13 @@ public class ChimeraViewFrame extends StructureViewerBase
    */
   private String chimeraSessionFile = null;
 
-  private Random random = new Random();
+  private int myWidth = 500;
+
+  private int myHeight = 150;
+
+  private JMenuItem writeFeatures = null;
+
+  private JMenu fetchAttributes = null;
 
   /**
    * Initialise menu options.
@@ -84,21 +85,13 @@ public class ChimeraViewFrame extends StructureViewerBase
   {
     super.initMenus();
 
-    viewerActionMenu.setText(MessageManager.getString("label.chimera"));
-
-    viewerColour.setText(MessageManager
-            .getString("label.colour_with_chimera"));
-    viewerColour.setToolTipText(MessageManager
-            .getString("label.let_chimera_manage_structure_colours"));
-
-    helpItem.setText(MessageManager.getString("label.chimera_help"));
     savemenu.setVisible(false); // not yet implemented
     viewMenu.add(fitToWindow);
 
-    JMenuItem writeFeatures = new JMenuItem(
-            MessageManager.getString("label.create_chimera_attributes"));
-    writeFeatures.setToolTipText(MessageManager
-            .getString("label.create_chimera_attributes_tip"));
+    writeFeatures = new JMenuItem(
+            MessageManager.getString("label.create_viewer_attributes"));
+    writeFeatures.setToolTipText(
+            MessageManager.getString("label.create_viewer_attributes_tip"));
     writeFeatures.addActionListener(new ActionListener()
     {
       @Override
@@ -109,10 +102,10 @@ public class ChimeraViewFrame extends StructureViewerBase
     });
     viewerActionMenu.add(writeFeatures);
 
-    final JMenu fetchAttributes = new JMenu(
-            MessageManager.getString("label.fetch_chimera_attributes"));
-    fetchAttributes.setToolTipText(MessageManager
-            .getString("label.fetch_chimera_attributes_tip"));
+    fetchAttributes = new JMenu(MessageManager.formatMessage(
+            "label.fetch_viewer_attributes", getViewerName()));
+    fetchAttributes.setToolTipText(MessageManager.formatMessage(
+            "label.fetch_viewer_attributes_tip", getViewerName()));
     fetchAttributes.addMouseListener(new MouseAdapter()
     {
 
@@ -123,73 +116,62 @@ public class ChimeraViewFrame extends StructureViewerBase
       }
     });
     viewerActionMenu.add(fetchAttributes);
-
   }
 
+  @Override
+  protected void buildActionMenu()
+  {
+    super.buildActionMenu();
+    // add these back in after menu is refreshed
+    viewerActionMenu.add(writeFeatures);
+    viewerActionMenu.add(fetchAttributes);
+
+  };
+
   /**
-   * Query Chimera for its residue attribute names and add them as items off the
-   * attributes menu
+   * Query the structure viewer for its residue attribute names and add them as
+   * items off the attributes menu
    * 
    * @param attributesMenu
    */
   protected void buildAttributesMenu(JMenu attributesMenu)
   {
-    List<String> atts = jmb.sendChimeraCommand("list resattr", true);
-    if (atts == null)
-    {
-      return;
-    }
+    List<String> atts = jmb.getChimeraAttributes();
     attributesMenu.removeAll();
     Collections.sort(atts);
-    for (String att : atts)
+    for (String attName : atts)
     {
-      final String attName = att.split(" ")[1];
-
-      /*
-       * ignore 'jv_*' attributes, as these are Jalview features that have
-       * been transferred to residue attributes in Chimera!
-       */
-      if (!attName.startsWith(ChimeraCommands.NAMESPACE_PREFIX))
+      JMenuItem menuItem = new JMenuItem(attName);
+      menuItem.addActionListener(new ActionListener()
       {
-        JMenuItem menuItem = new JMenuItem(attName);
-        menuItem.addActionListener(new ActionListener()
+        @Override
+        public void actionPerformed(ActionEvent e)
         {
-          @Override
-          public void actionPerformed(ActionEvent e)
+          if (getBinding().copyStructureAttributesToFeatures(attName,
+                  getAlignmentPanel()) > 0)
           {
-            getChimeraAttributes(attName);
+            getAlignmentPanel().getFeatureRenderer().featuresAdded();
           }
-        });
-        attributesMenu.add(menuItem);
-      }
+        }
+      });
+      attributesMenu.add(menuItem);
     }
   }
 
   /**
-   * Read residues in Chimera with the given attribute name, and set as features
-   * on the corresponding sequence positions (if any)
-   * 
-   * @param attName
-   */
-  protected void getChimeraAttributes(String attName)
-  {
-    jmb.copyStructureAttributesToFeatures(attName, getAlignmentPanel());
-  }
-
-  /**
-   * 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
+   * Sends command(s) to the structure viewer to create residue attributes for
+   * visible Jalview features
    */
   protected void sendFeaturesToChimera()
   {
-    jmb.sendFeaturesToViewer(getAlignmentPanel());
+    // todo pull up?
+    int count = jmb.sendFeaturesToViewer(getAlignmentPanel());
+    statusBar.setText(MessageManager.formatMessage("label.attributes_set",
+            count, getViewerName()));
   }
 
   /**
-   * add a single PDB structure to a new or existing Chimera view
+   * open a single PDB structure in a new Chimera view
    * 
    * @param pdbentry
    * @param seq
@@ -200,32 +182,10 @@ public class ChimeraViewFrame extends StructureViewerBase
           String[] chains, final AlignmentPanel ap)
   {
     this();
-    String pdbId = pdbentry.getId();
-
-    /*
-     * If the PDB file is already loaded, the user may just choose to add to an
-     * existing viewer (or cancel)
-     */
-    if (addAlreadyLoadedFile(seq, chains, ap, pdbId))
-    {
-      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 (or cancel)
-     */
-    if (addToExistingViewer(pdbentry, seq, chains, ap, pdbId))
-    {
-      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 });
+            new SequenceI[][]
+            { seq });
   }
 
   /**
@@ -233,9 +193,9 @@ public class ChimeraViewFrame extends StructureViewerBase
    */
   protected void createProgressBar()
   {
-    if (progressBar == null)
+    if (getProgressIndicator() == null)
     {
-      progressBar = new ProgressBar(statusPanel, statusBar);
+      setProgressIndicator(new ProgressBar(statusPanel, statusBar));
     }
   }
 
@@ -243,28 +203,27 @@ public class ChimeraViewFrame extends StructureViewerBase
           SequenceI[][] seqs)
   {
     createProgressBar();
-    jmb = new JalviewChimeraBindingModel(this,
-            ap.getStructureSelectionManager(), pdbentrys, seqs, null);
+    jmb = newBindingModel(ap, pdbentrys, seqs);
     addAlignmentPanel(ap);
     useAlignmentPanelForColourbyseq(ap);
 
     if (pdbentrys.length > 1)
     {
-      alignAddedStructures = true;
       useAlignmentPanelForSuperposition(ap);
     }
     jmb.setColourBySequence(true);
-    setSize(400, 400); // probably should be a configurable/dynamic default here
+    setSize(myWidth, myHeight);
     initMenus();
 
     addingStructures = false;
-    worker = new Thread(this);
+    worker = new Thread(this, "OpenChimera");
     worker.start();
 
     this.addInternalFrameListener(new InternalFrameAdapter()
     {
       @Override
-      public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
+      public void internalFrameClosing(
+              InternalFrameEvent internalFrameEvent)
       {
         closeViewer(false);
       }
@@ -272,6 +231,13 @@ public class ChimeraViewFrame extends StructureViewerBase
 
   }
 
+  protected JalviewChimeraBindingModel newBindingModel(AlignmentPanel ap,
+          PDBEntry[] pdbentrys, SequenceI[][] seqs)
+  {
+    return new JalviewChimeraBindingModel(this,
+            ap.getStructureSelectionManager(), pdbentrys, seqs, null);
+  }
+
   /**
    * Create a new viewer from saved session state data including Chimera session
    * file
@@ -284,22 +250,34 @@ public class ChimeraViewFrame extends StructureViewerBase
    * @param colourBySequence
    * @param newViewId
    */
-  public ChimeraViewFrame(String chimeraSessionFile,
-          AlignmentPanel alignPanel, PDBEntry[] pdbArray,
-          SequenceI[][] seqsArray, boolean colourByChimera,
-          boolean colourBySequence, String newViewId)
+  public ChimeraViewFrame(StructureViewerModel viewerData,
+          AlignmentPanel alignPanel, String sessionFile, String vid)
   {
     this();
-    setViewId(newViewId);
-    this.chimeraSessionFile = chimeraSessionFile;
+    setViewId(vid);
+    this.chimeraSessionFile = sessionFile;
+    Map<File, StructureData> pdbData = viewerData.getFileData();
+    PDBEntry[] pdbArray = new PDBEntry[pdbData.size()];
+    SequenceI[][] seqsArray = new SequenceI[pdbData.size()][];
+    int i = 0;
+    for (StructureData data : pdbData.values())
+    {
+      PDBEntry pdbentry = new PDBEntry(data.getPdbId(), null,
+              PDBEntry.Type.PDB, data.getFilePath());
+      pdbArray[i] = pdbentry;
+      List<SequenceI> sequencesForPdb = data.getSeqList();
+      seqsArray[i] = sequencesForPdb
+              .toArray(new SequenceI[sequencesForPdb.size()]);
+      i++;
+    }
     openNewChimera(alignPanel, pdbArray, seqsArray);
-    if (colourByChimera)
+    if (viewerData.isColourByViewer())
     {
       jmb.setColourBySequence(false);
       seqColour.setSelected(false);
       viewerColour.setSelected(true);
     }
-    else if (colourBySequence)
+    else if (viewerData.isColourWithAlignPanel())
     {
       jmb.setColourBySequence(true);
       seqColour.setSelected(true);
@@ -308,17 +286,18 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   /**
-   * create a new viewer containing several structures superimposed using the
-   * given alignPanel.
+   * create a new viewer containing several structures, optionally superimposed
+   * using the given alignPanel.
    * 
    * @param pe
    * @param seqs
    * @param ap
    */
-  public ChimeraViewFrame(PDBEntry[] pe, SequenceI[][] seqs,
-          AlignmentPanel ap)
+  public ChimeraViewFrame(PDBEntry[] pe, boolean alignAdded,
+          SequenceI[][] seqs, AlignmentPanel ap)
   {
     this();
+    setAlignAddedStructures(alignAdded);
     openNewChimera(ap, pe, seqs);
   }
 
@@ -337,29 +316,6 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   /**
-   * 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.
-   */
-  @Override
-  protected List<StructureViewerBase> getViewersFor(AlignmentPanel ap)
-  {
-    List<StructureViewerBase> result = new ArrayList<StructureViewerBase>();
-    JInternalFrame[] frames = Desktop.instance.getAllFrames();
-
-    for (JInternalFrame frame : frames)
-    {
-      if (frame instanceof ChimeraViewFrame)
-      {
-        if (ap == null || ((StructureViewerBase) frame).isLinkedWith(ap))
-        {
-          result.add((StructureViewerBase) frame);
-        }
-      }
-    }
-    return result;
-  }
-
-  /**
    * Launch Chimera. If we have a chimera session file name, send Chimera the
    * command to open its saved session file.
    */
@@ -373,9 +329,11 @@ public class ChimeraViewFrame extends StructureViewerBase
     if (!jmb.launchChimera())
     {
       JvOptionPane.showMessageDialog(Desktop.desktop,
-              MessageManager.getString("label.chimera_failed"),
+              MessageManager.formatMessage("label.open_viewer_failed",
+                      getViewerName()),
               MessageManager.getString("label.error_loading_file"),
               JvOptionPane.ERROR_MESSAGE);
+      jmb.closeViewer(true);
       this.dispose();
       return;
     }
@@ -385,9 +343,8 @@ public class ChimeraViewFrame extends StructureViewerBase
       boolean opened = jmb.openSession(chimeraSessionFile);
       if (!opened)
       {
-        System.err
-                .println("An error occurred opening Chimera session file "
-                        + chimeraSessionFile);
+        System.err.println("An error occurred opening Chimera session file "
+                + chimeraSessionFile);
       }
     }
 
@@ -395,72 +352,6 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   /**
-   * Show only the selected chain(s) in the viewer
-   */
-  @Override
-  void showSelectedChains()
-  {
-    List<String> toshow = new ArrayList<String>();
-    for (int i = 0; i < chainMenu.getItemCount(); i++)
-    {
-      if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
-      {
-        JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
-        if (item.isSelected())
-        {
-          toshow.add(item.getText());
-        }
-      }
-    }
-    jmb.showChains(toshow);
-  }
-
-  /**
-   * Close down this instance of Jalview's Chimera viewer, giving the user the
-   * option to close the associated Chimera window (process). They may wish to
-   * keep it open until they have had an opportunity to save any work.
-   * 
-   * @param closeChimera
-   *          if true, close any linked Chimera process; if false, prompt first
-   */
-  @Override
-  public void closeViewer(boolean closeChimera)
-  {
-    if (jmb != null && jmb.isChimeraRunning())
-    {
-      if (!closeChimera)
-      {
-        String prompt = MessageManager.formatMessage(
-                "label.confirm_close_chimera",
-                        new Object[] { jmb.getViewerTitle(getViewerName(),
-                                false) });
-        prompt = JvSwingUtils.wrapTooltip(true, prompt);
-        int confirm = JvOptionPane.showConfirmDialog(this, prompt,
-                MessageManager.getString("label.close_viewer"),
-                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);
-    }
-    setAlignmentPanel(null);
-    _aps.clear();
-    _alignwith.clear();
-    _colourwith.clear();
-    // 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).
    */
@@ -471,13 +362,13 @@ public class ChimeraViewFrame extends StructureViewerBase
     // todo - record which pdbids were successfully imported.
     StringBuilder errormsgs = new StringBuilder(128);
     StringBuilder files = new StringBuilder(128);
-    List<PDBEntry> filePDB = new ArrayList<PDBEntry>();
-    List<Integer> filePDBpos = new ArrayList<Integer>();
+    List<PDBEntry> filePDB = new ArrayList<>();
+    List<Integer> filePDBpos = new ArrayList<>();
     PDBEntry thePdbEntry = null;
     StructureFile pdb = null;
     try
     {
-      String[] curfiles = jmb.getPdbFile(); // files currently in viewer
+      String[] curfiles = jmb.getStructureFiles(); // files currently in viewer
       // TODO: replace with reference fetching/transfer code (validate PDBentry
       // as a DBRef?)
       for (int pi = 0; pi < jmb.getPdbCount(); pi++)
@@ -519,7 +410,7 @@ public class ChimeraViewFrame extends StructureViewerBase
         {
           filePDB.add(thePdbEntry);
           filePDBpos.add(Integer.valueOf(pi));
-          files.append(" \"" + Platform.escapeString(file) + "\"");
+          files.append(" \"" + Platform.escapeBackslashes(file) + "\"");
         }
       }
     } catch (OutOfMemoryError oomerror)
@@ -529,15 +420,16 @@ public class ChimeraViewFrame extends StructureViewerBase
     } catch (Exception ex)
     {
       ex.printStackTrace();
-      errormsgs.append("When retrieving pdbfiles for '"
-              + thePdbEntry.getId() + "'");
+      errormsgs.append(
+              "When retrieving pdbfiles for '" + thePdbEntry.getId() + "'");
     }
     if (errormsgs.length() > 0)
     {
 
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
-              .formatMessage("label.pdb_entries_couldnt_be_retrieved",
-                      new Object[] { errormsgs.toString() }),
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage(
+                      "label.pdb_entries_couldnt_be_retrieved", new Object[]
+                      { errormsgs.toString() }),
               MessageManager.getString("label.couldnt_load_file"),
               JvOptionPane.ERROR_MESSAGE);
     }
@@ -552,9 +444,15 @@ public class ChimeraViewFrame extends StructureViewerBase
           initChimera();
         } catch (Exception ex)
         {
-          Cache.log.error("Couldn't open Chimera viewer!", ex);
+          Console.error("Couldn't open Chimera viewer!", ex);
         }
       }
+      if (!jmb.isViewerRunning())
+      {
+        // nothing to do
+        // TODO: ensure we tidy up JAL-3619
+        return;
+      }
       int num = -1;
       for (PDBEntry pe : filePDB)
       {
@@ -584,9 +482,12 @@ public class ChimeraViewFrame extends StructureViewerBase
               stopProgressBar("", startTime);
             }
             // Explicitly map to the filename used by Chimera ;
+
             pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
-                    jmb.getChains()[pos], pe.getFile(), protocol);
-            stashFoundChains(pdb, pe.getFile());
+                    jmb.getChains()[pos], pe.getFile(), protocol,
+                    getProgressIndicator());
+            jmb.stashFoundChains(pdb, pe.getFile());
+
           } catch (OutOfMemoryError oomerror)
           {
             new OOMWarning(
@@ -594,11 +495,12 @@ public class ChimeraViewFrame extends StructureViewerBase
                     oomerror);
           } catch (Exception ex)
           {
-            Cache.log.error("Couldn't open " + pe.getFile()
-                    + " in Chimera viewer!", ex);
+            Console.error(
+                    "Couldn't open " + pe.getFile() + " in Chimera viewer!",
+                    ex);
           } finally
           {
-            Cache.log.debug("File locations are " + files);
+            Console.debug("File locations are " + files);
           }
         }
       }
@@ -607,23 +509,33 @@ public class ChimeraViewFrame extends StructureViewerBase
       jmb.setFinishedInit(true);
       jmb.setLoadingFromArchive(false);
 
+      /*
+       * ensure that any newly discovered features (e.g. RESNUM)
+       * are notified to the FeatureRenderer (and added to any 
+       * open feature settings dialog)
+       */
+      FeatureRenderer fr = getBinding().getFeatureRenderer(null);
+      if (fr != null)
+      {
+        fr.featuresAdded();
+      }
+
       // refresh the sequence colours for the new structure(s)
-      for (AlignmentPanel ap : _colourwith)
+      for (AlignmentViewPanel ap : _colourwith)
       {
         jmb.updateColours(ap);
       }
       // do superposition if asked to
-      if (Cache.getDefault("AUTOSUPERIMPOSE", true) && alignAddedStructures)
+      if (alignAddedStructures)
       {
         new Thread(new Runnable()
         {
           @Override
           public void run()
           {
-            alignStructs_withAllAlignPanels();
+            alignStructsWithAllAlignPanels();
           }
         }).start();
-        alignAddedStructures = false;
       }
       addingStructures = false;
     }
@@ -631,130 +543,11 @@ public class ChimeraViewFrame extends StructureViewerBase
     worker = null;
   }
 
-  /**
-   * Fetch PDB data and save to a local file. Returns the full path to the file,
-   * or null if fetch fails.
-   * 
-   * @param processingEntry
-   * @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;
-    String pdbid = processingEntry.getId();
-    long handle = System.currentTimeMillis()
-            + Thread.currentThread().hashCode();
-
-    /*
-     * Write 'fetching PDB' progress on AlignFrame as we are not yet visible
-     */
-    String msg = MessageManager.formatMessage("status.fetching_pdb",
-            new Object[] { pdbid });
-    getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
-    // long hdl = startProgressBar(MessageManager.formatMessage(
-    // "status.fetching_pdb", new Object[]
-    // { pdbid }));
-    try
-    {
-      pdbseq = pdbclient.getSequenceRecords(pdbid);
-    } catch (OutOfMemoryError oomerror)
-    {
-      new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
-    } finally
-    {
-      msg = pdbid + " " + MessageManager.getString("label.state_completed");
-      getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
-      // stopProgressBar(msg, hdl);
-    }
-    /*
-     * If PDB data were saved and are not invalid (empty alignment), return the
-     * file path.
-     */
-    if (pdbseq != null && pdbseq.getHeight() > 0)
-    {
-      // just use the file name from the first sequence's first PDBEntry
-      filePath = new File(pdbseq.getSequenceAt(0).getAllPDBEntries()
-              .elementAt(0).getFile()).getAbsolutePath();
-      processingEntry.setFile(filePath);
-    }
-    return filePath;
-  }
-
-  /**
-   * Convenience method to update the progress bar if there is one. Be sure to
-   * call stopProgressBar with the returned handle to remove the message.
-   * 
-   * @param msg
-   * @param handle
-   */
-  public long startProgressBar(String msg)
-  {
-    // TODO would rather have startProgress/stopProgress as the
-    // IProgressIndicator interface
-    long tm = random.nextLong();
-    if (progressBar != null)
-    {
-      progressBar.setProgressBar(msg, tm);
-    }
-    return tm;
-  }
-
-  /**
-   * End the progress bar with the specified handle, leaving a message (if not
-   * null) on the status bar
-   * 
-   * @param msg
-   * @param handle
-   */
-  public void stopProgressBar(String msg, long handle)
-  {
-    if (progressBar != null)
-    {
-      progressBar.setProgressBar(msg, handle);
-    }
-  }
-
-  @Override
-  public void eps_actionPerformed(ActionEvent e)
-  {
-    throw new Error(
-            MessageManager
-                    .getString("error.eps_generation_not_implemented"));
-  }
-
   @Override
-  public void png_actionPerformed(ActionEvent e)
+  public void makePDBImage(TYPE imageType)
   {
-    throw new Error(
-            MessageManager
-                    .getString("error.png_generation_not_implemented"));
-  }
-
-  @Override
-  public void showHelp_actionPerformed(ActionEvent actionEvent)
-  {
-    try
-    {
-      BrowserLauncher
-              .openURL("https://www.cgl.ucsf.edu/chimera/docs/UsersGuide");
-    } catch (IOException ex)
-    {
-    }
+    throw new UnsupportedOperationException(
+            "Image export for Chimera is not implemented");
   }
 
   @Override
@@ -763,82 +556,6 @@ public class ChimeraViewFrame extends StructureViewerBase
     return jmb;
   }
 
-  /**
-   * Ask Chimera to save its session to the designated file path, or to a
-   * temporary file if the path is null. Returns the file path if successful,
-   * else null.
-   * 
-   * @param filepath
-   * @see getStateInfo
-   */
-  protected String saveSession(String filepath)
-  {
-    String pathUsed = filepath;
-    try
-    {
-      if (pathUsed == null)
-      {
-        File tempFile = File.createTempFile("chimera", ".py");
-        tempFile.deleteOnExit();
-        pathUsed = tempFile.getPath();
-      }
-      boolean result = jmb.saveSession(pathUsed);
-      if (result)
-      {
-        this.chimeraSessionFile = pathUsed;
-        return pathUsed;
-      }
-    } catch (IOException e)
-    {
-    }
-    return null;
-  }
-
-  /**
-   * Returns a string representing the state of the Chimera session. This is
-   * done by requesting Chimera to save its session to a temporary file, then
-   * reading the file contents. Returns an empty string on any error.
-   */
-  @Override
-  public String getStateInfo()
-  {
-    String sessionFile = saveSession(null);
-    if (sessionFile == null)
-    {
-      return "";
-    }
-    InputStream is = null;
-    try
-    {
-      File f = new File(sessionFile);
-      byte[] bytes = new byte[(int) f.length()];
-      is = new FileInputStream(sessionFile);
-      is.read(bytes);
-      return new String(bytes);
-    } catch (IOException e)
-    {
-      return "";
-    } finally
-    {
-      if (is != null)
-      {
-        try
-        {
-          is.close();
-        } catch (IOException e)
-        {
-          // ignore
-        }
-      }
-    }
-  }
-
-  @Override
-  protected void fitToWindow_actionPerformed()
-  {
-    jmb.focusView();
-  }
-
   @Override
   public ViewerType getViewerType()
   {
@@ -850,21 +567,4 @@ public class ChimeraViewFrame extends StructureViewerBase
   {
     return "Chimera";
   }
-
-  /**
-   * Override superclass method to make the 'Chimera' menu always visible, but
-   * 'Superpose with...' only enabled if there is more than one structure shown
-   */
-  @Override
-  public void updateTitleAndMenus()
-  {
-    super.updateTitleAndMenus();
-    viewerActionMenu.setVisible(true);
-    viewSelectionMenu.setEnabled(false);
-    if (getBinding().getPdbFile().length > 1
-            && getBinding().getSequence().length > 1)
-    {
-      viewSelectionMenu.setEnabled(true);
-    }
-  }
 }