Merge branch 'develop' into features/JAL-2295setChimeraAttributes
[jalview.git] / src / jalview / gui / ChimeraViewFrame.java
index b82eef3..4c38898 100644 (file)
@@ -26,6 +26,7 @@ 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;
@@ -47,8 +48,11 @@ 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;
@@ -58,6 +62,7 @@ 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.Random;
 import java.util.Vector;
@@ -66,6 +71,7 @@ import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JColorChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
+import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
@@ -180,6 +186,97 @@ 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);
+
+  }
+
+  /**
+   * Query Chimera 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;
+    }
+    attributesMenu.removeAll();
+    Collections.sort(atts);
+    for (String att : 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()
+        {
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            getChimeraAttributes(attName);
+          }
+        });
+        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
+   */
+  protected void sendFeaturesToChimera()
+  {
+    jmb.sendFeaturesToViewer(getAlignmentPanel());
   }
 
   /**
@@ -246,7 +343,6 @@ public class ChimeraViewFrame extends StructureViewerBase
           SequenceI[][] seqs)
   {
     createProgressBar();
-    // FIXME extractChains needs pdbentries to match IDs to PDBEntry(s) on seqs
     jmb = new JalviewChimeraBindingModel(this,
             ap.getStructureSelectionManager(), pdbentrys, seqs, null);
     addAlignmentPanel(ap);
@@ -275,8 +371,6 @@ public class ChimeraViewFrame extends StructureViewerBase
 
   }
 
-
-
   /**
    * Create a new viewer from saved session state data including Chimera session
    * file
@@ -370,10 +464,8 @@ public class ChimeraViewFrame extends StructureViewerBase
    */
   void initChimera()
   {
-    jmb.setFinishedInit(false);
-    jalview.gui.Desktop.addInternalFrame(this,
-            jmb.getViewerTitle("Chimera", true), getBounds().width,
-            getBounds().height);
+    Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true),
+            getBounds().width, getBounds().height);
 
     if (!jmb.launchChimera())
     {
@@ -395,11 +487,64 @@ public class ChimeraViewFrame extends StructureViewerBase
                         + chimeraSessionFile);
       }
     }
-    jmb.setFinishedInit(true);
 
     jmb.startChimeraListener();
   }
 
+  /**
+   * If the list is not empty, add menu items for 'All' and each individual
+   * chain to the "View | Show Chain" sub-menu. Multiple selections are allowed.
+   * 
+   * @param chainNames
+   */
+  @Override
+  void setChainMenuItems(List<String> chainNames)
+  {
+    chainMenu.removeAll();
+    if (chainNames == null || chainNames.isEmpty())
+    {
+      return;
+    }
+    JMenuItem menuItem = new JMenuItem(
+            MessageManager.getString("label.all"));
+    menuItem.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent evt)
+      {
+        allChainsSelected = true;
+        for (int i = 0; i < chainMenu.getItemCount(); i++)
+        {
+          if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
+          {
+            ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
+          }
+        }
+        showSelectedChains();
+        allChainsSelected = false;
+      }
+    });
+
+    chainMenu.add(menuItem);
+
+    for (String chainName : chainNames)
+    {
+      menuItem = new JCheckBoxMenuItem(chainName, true);
+      menuItem.addItemListener(new ItemListener()
+      {
+        @Override
+        public void itemStateChanged(ItemEvent evt)
+        {
+          if (!allChainsSelected)
+          {
+            showSelectedChains();
+          }
+        }
+      });
+
+      chainMenu.add(menuItem);
+    }
+  }
 
   /**
    * Show only the selected chain(s) in the viewer
@@ -550,6 +695,7 @@ public class ChimeraViewFrame extends StructureViewerBase
 
     if (files.length() > 0)
     {
+      jmb.setFinishedInit(false);
       if (!addingStructures)
       {
         try
@@ -607,6 +753,7 @@ public class ChimeraViewFrame extends StructureViewerBase
           }
         }
       }
+
       jmb.refreshGUI();
       jmb.setFinishedInit(true);
       jmb.setLoadingFromArchive(false);
@@ -965,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);