JAL-3949 - refactor logging from jalview.bin.Cache to jalview.bin.Console
[jalview.git] / src / jalview / gui / ChimeraViewFrame.java
index 1a5e901..9d98585 100644 (file)
  */
 package jalview.gui;
 
-import jalview.api.AlignmentViewPanel;
-import jalview.api.FeatureRenderer;
-import jalview.bin.Cache;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceI;
-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.Map;
 
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
@@ -54,6 +36,22 @@ 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
  * 
@@ -75,7 +73,10 @@ public class ChimeraViewFrame extends StructureViewerBase
 
   private int myHeight = 150;
 
-  /**
+  private JMenuItem writeFeatures=null;
+
+  private JMenu fetchAttributes=null;
+/**
    * Initialise menu options.
    */
   @Override
@@ -83,21 +84,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 = new JMenuItem(
+            MessageManager.getString("label.create_viewer_attributes"));
     writeFeatures.setToolTipText(MessageManager
-            .getString("label.create_chimera_attributes_tip"));
+            .getString("label.create_viewer_attributes_tip"));
     writeFeatures.addActionListener(new ActionListener()
     {
       @Override
@@ -108,10 +101,10 @@ public class ChimeraViewFrame extends StructureViewerBase
     });
     viewerActionMenu.add(writeFeatures);
 
-    final JMenu fetchAttributes = new JMenu(
-            MessageManager.getString("label.fetch_chimera_attributes"));
+    fetchAttributes = new JMenu(
+            MessageManager.formatMessage("label.fetch_viewer_attributes",getViewerName()));
     fetchAttributes.setToolTipText(
-            MessageManager.getString("label.fetch_chimera_attributes_tip"));
+            MessageManager.formatMessage("label.fetch_viewer_attributes_tip",getViewerName()));
     fetchAttributes.addMouseListener(new MouseAdapter()
     {
 
@@ -123,10 +116,18 @@ 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
    */
@@ -143,7 +144,11 @@ public class ChimeraViewFrame extends StructureViewerBase
         @Override
         public void actionPerformed(ActionEvent e)
         {
-          getChimeraAttributes(attName);
+          if (getBinding().copyStructureAttributesToFeatures(attName,
+                  getAlignmentPanel()) > 0)
+          {
+            getAlignmentPanel().getFeatureRenderer().featuresAdded();
+          }
         }
       });
       attributesMenu.add(menuItem);
@@ -151,28 +156,15 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   /**
-   * 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 &lt;attName&gt; &lt;attValue&gt; &lt;atomSpec&gt;
-   * <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()
   {
+    // todo pull up?
     int count = jmb.sendFeaturesToViewer(getAlignmentPanel());
     statusBar.setText(
-            MessageManager.formatMessage("label.attributes_set", count));
+            MessageManager.formatMessage("label.attributes_set", count, getViewerName()));
   }
 
   /**
@@ -255,22 +247,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);
@@ -323,7 +327,8 @@ 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);
       this.dispose();
@@ -344,50 +349,6 @@ public class ChimeraViewFrame extends StructureViewerBase
   }
 
   /**
-   * 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).
    */
@@ -480,7 +441,7 @@ 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);
         }
       }
       int num = -1;
@@ -516,7 +477,7 @@ public class ChimeraViewFrame extends StructureViewerBase
             pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
                     jmb.getChains()[pos], pe.getFile(), protocol,
                     getProgressIndicator());
-            stashFoundChains(pdb, pe.getFile());
+            jmb.stashFoundChains(pdb, pe.getFile());
 
           } catch (OutOfMemoryError oomerror)
           {
@@ -525,12 +486,12 @@ public class ChimeraViewFrame extends StructureViewerBase
                     oomerror);
           } catch (Exception ex)
           {
-            Cache.log.error(
+            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);
           }
         }
       }
@@ -541,7 +502,8 @@ public class ChimeraViewFrame extends StructureViewerBase
 
       /*
        * ensure that any newly discovered features (e.g. RESNUM)
-       * are added to any open feature settings dialog
+       * are notified to the FeatureRenderer (and added to any 
+       * open feature settings dialog)
        */
       FeatureRenderer fr = getBinding().getFeatureRenderer(null);
       if (fr != null)
@@ -572,97 +534,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. TODO: refactor to common with Jmol ? duplication
-   * 
-   * @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.addChainFile(chid, file);
-    }
-  }
-
-  private String fetchPdbFile(PDBEntry processingEntry) throws Exception
-  {
-    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;
-  }
-
   @Override
-  public void eps_actionPerformed()
+  public void makePDBImage(TYPE imageType)
   {
-    throw new Error(MessageManager
-            .getString("error.eps_generation_not_implemented"));
-  }
-
-  @Override
-  public void png_actionPerformed()
-  {
-    throw new Error(MessageManager
-            .getString("error.png_generation_not_implemented"));
-  }
-
-  @Override
-  public void showHelp_actionPerformed()
-  {
-    try
-    {
-      String url = jmb.getHelpURL();
-      BrowserLauncher.openURL(url);
-    } catch (IOException ex)
-    {
-      System.err
-              .println("Show Chimera help failed with: " + ex.getMessage());
-    }
+    throw new UnsupportedOperationException(
+            "Image export for Chimera is not implemented");
   }
 
   @Override
@@ -671,83 +547,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)
-      {
-        String suffix = jmb.getSessionFileExtension();
-        File tempFile = File.createTempFile("chimera", suffix);
-        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()
   {