Merge branch 'mrg_dev_282' into Release_2_8_2_Branch
authorJim Procter <jprocter@dundee.ac.uk>
Mon, 17 Nov 2014 10:40:02 +0000 (10:40 +0000)
committerJim Procter <jprocter@dundee.ac.uk>
Mon, 17 Nov 2014 10:40:02 +0000 (10:40 +0000)
20 files changed:
help/help.jhm
help/helpTOC.xml
help/html/features/chimera.html [new file with mode: 0644]
help/html/features/jmol.html
help/html/features/preferences.html
help/html/features/viewingpdbs.html
resources/lang/Messages.properties
src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java
src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java
src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java
src/jalview/bin/Cache.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AppJmol.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/JalviewChimeraBindingModel.java
src/jalview/gui/Preferences.java
src/jalview/gui/StructureViewer.java
src/jalview/jbgui/GPreferences.java
src/jalview/jbgui/GStructureViewer.java
src/jalview/structure/StructureSelectionManager.java

index 7750265..c6cc626 100755 (executable)
@@ -52,6 +52,7 @@
    <mapID target="viewingpdbs.reps" url="html/features/viewingpdbs.html#viewreps"/>
    <mapID target="pdbmcviewer" url="html/features/pdbviewer.html"/>
    <mapID target="pdbjmol" url="html/features/jmol.html"/>
+   <mapID target="chimera" url="html/features/chimera.html"/>
    <mapID target="varna" url="html/features/varna.html"/>
    <mapID target="preferences" url="html/features/preferences.html"/>     
    <mapID target="commandline" url="html/features/commandline.html"/>
index 4c09e8f..6ae5c78 100755 (executable)
         </tocitem>
        <tocitem text="Viewing PDB Files" target="viewingpdbs" expand="false">
          <tocitem text="Jmol Viewer" target="pdbjmol"/>
+         <tocitem text="Chimera Viewer" target="chimera"/>
          <tocitem text="Simple PDB Viewer" target="pdbmcviewer"/>
        </tocitem>
        <tocitem text="Viewing RNA structures" target="varna" expand="false">   </tocitem>
diff --git a/help/html/features/chimera.html b/help/html/features/chimera.html
new file mode 100644 (file)
index 0000000..e866597
--- /dev/null
@@ -0,0 +1,172 @@
+<html>
+<!--
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
+ * Copyright (C) 2014 The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ -->
+<head>
+<title>The Chimera PDB Viewer</title>
+</head>
+<body>
+<p><strong>The Chimera Viewer</strong></p>
+<p>Since Jalview 2.8.2, <a href="https://www.cgl.ucsf.edu/chimera/">Chimera</a>
+has been integrated into Jalview for interactively viewing structures
+opened by entries in the <strong>&quot;Structure&quot;</strong> submenu in the <a href="../menus/popupMenu.html">sequence
+id pop-up menu</a> (if you can't see this, then you need to <a
+       href="viewingpdbs.html">associate a PDB structure</a> with the
+sequence). Chimera is available from the Jalview desktop, provided Chimera has been separately installed.</p>
+<p>You can set a default choice of Jmol or Chimera structure viewer in <a href="preferences.html#structure"> Preferences</a>. 
+You can also optionally specify the path to the Chimera program here (if it differs from the standard paths searched by Jalview).
+<p>The following menu entries are provided for viewing structure data<br>
+  <ul>
+    <li>The <strong>&quot;Structure&#8594;View
+        Structure&#8594;</strong> submenu allows a single PDB structure to be chosen
+      for display from the available structures for a sequence.
+    </li>
+    <li>The <strong>&quot;Structure&#8594;View all <em>N</em>
+        structures
+    </strong> option will open a new window containing all structures associated
+      with the current selection.
+    </li>
+    <li>The <strong>&quot;Structure&#8594;View all <em>N</em>
+        representative structures
+    </strong> option will open a new window containing exactly one structure per
+      currently selected sequence.<br /></li>
+  </ul>
+  <br> 
+</p>
+<p><a name="align"><strong>Superposing structures based
+on their aligned sequences</strong></a><br>
+<p>If several structures are available on the alignment, you may add
+additional structures to an existing Chimera view by selecting their entry
+in the appropriate pop-up menu. Jalview will ask you if you wish to add
+the structure to the existing alignment, and if you do, it will import
+and superimpose the new PDB file using the corresponding positions from
+the alignment. If the alignment is subsequently edited, you can use the
+<a href="#sAlign"><em>Chimera&#8594;Align</em></a> menu option from the
+menu bar of the structure view window to superpose the structures using
+the updated alignment.<br>
+</p>
+<p><strong>Chimera Controls</strong><br>
+<p>The structure is by default rendered as a ribbon diagram. Moving the
+mouse over the structure brings up tooltips giving the residue name, PDB
+residue number and chain code
+([RES]Num:Chain). Moving the mouse over an
+associated residue in an alignment window highlights the associated
+atoms in the displayed structures. For comprehensive details of Chimera's commands, refer to the tool's Help menu.</p>
+<p>Basic screen operations (see <a href="https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/mouse.html">Chimera help</a> for full details).
+<table border="1">
+       <tr>
+               <td><strong>Action</strong></td>
+               <td><strong>Windows</strong></td>
+               <td><strong>Unix</strong></td>
+               <td><strong>Mac/OSX</strong></td>
+       </tr>
+       <tr>
+               <td>Rotate View</td>
+               <td>Left Click and Drag</td>
+               <td>Left Click and Drag</td>
+               <td>Left Click and Drag</td>
+       </tr>
+       <tr>
+               <td>Zoom</td><td>Right Click<br>
+               drag mouse up or down</td>
+               <td>Right Click<br>drag mouse up or down</td>
+               <td>cmd or Right + Click and drag mouse up or down, <br>or use mouse scroll button</td>
+       </tr>
+       <tr>
+               <td>Move Origin</td>
+               <td>Middle Button + Drag</td>
+               <td>Middle Button and drag</td>
+               <td>alt + Click<br>
+               and drag</td>
+       </tr>
+</table>
+</p>
+<p><strong>Jalview Controls</strong>
+<p>The Jalview Chimera View window has up to five menus:
+<ul>
+       <li><Strong>File<br>
+       </strong>
+       <ul>
+               <li><strong>View Mapping<br>
+               </strong><em> Opens a text window showing the alignment between the
+               residues corresponding to alpha-carbon atoms in the PDB structure and
+               the residues in the associated sequence.</em></li>
+       </ul>
+       </li>
+       <li><strong>View</strong>
+       <ul>
+               <li><strong>Show Chains<br>
+               </strong><em>Select which of the PDB file's chains (if more than one) are to be displayed.</em></li>
+               <li><strong>Colour by ..<br></strong><em>Submenu allowing specific alignment views to be selected for colouring associated chains in the structure display. This menu contains all the alignment views associated with the structure view, with those used to colour the view indicated by ticks. Addditionally, it contains the following menu entries:</em>
+               <ul><li><strong>Select many views<br></strong><em>When this option is enabled, selecting an alignment view adds it to the set used to colour the structures. Use this when colouring structures related to a number of alignments involving different domains or chains which are shown in the same structure view.</em>
+               </li>
+    <li><strong>Select all views<br></strong><em>This is only enabled when </em><strong>Select many views</strong><em> is also enabled, and will add all associated views to the set used to colour the structure display.</em>
+  </li>
+    <li><strong>Invert selection<br></strong><em>This is only enabled when </em><strong>Select many views</strong><em> is also enabled, and will replace the current set of views with any remaining views not currently used to colour the structure display.</em>
+  </li></ul></li></ul>
+       <li><strong>Colours<br>
+       </strong>
+       <ul>
+               <li><strong>By Sequence<br>
+               </strong><em> Colours each residue in the structure with the colour of its
+               corresponding residue in the associated sequence as rendered in the
+               associated alignment views, including any Uniprot sequence features or
+               region colourings.<br/>Pick which of the associated alignment views are used to colour the structures using the <strong>View&#8594;Colour by ..</strong> sub menu.</em><br>
+               Residues which only exist in the PDB structure are coloured white if
+               they are insertions (relative to the associated sequence in the
+               alignment) and grey if they are N or C terminal flanks outside the
+               region mapped to the alignment window's sequence.</em></li>
+               <li><strong>Charge &amp; Cysteine<br>
+               </strong><em> Highlights cysteines in yellow, anionic (Aspartic Acid or
+               Glutamic Acid) residues in red, and cationic (Lysine or Arginine)
+               residues in blue.</em></li>
+               <li><strong>Colour with Chimera<br></strong><em>Defers any colouring operations to Chimera. Select this if you want to use the 
+               Chimera scripting interface or menu to modify the view directly.</em></li>
+               <li><strong>Standard and User Defined Jalview
+               colourschemes.<br>
+               </strong><em>The remaining entries apply the colourschemes available from
+               the standard and user defined <a href="../colourSchemes/index.html">amino
+               acid colours</a>.</em></li>
+       </ul>
+       </li>
+       <li><strong>Chimera<br>
+       </strong><em>This pulldown menu is only displayed if there are multiple
+       structures shown in the Chimera window, and Jalview can also locate at
+       least two of the structures in the currently associated alignment view.</em>
+       <ul>
+               <li><strong><a name="sAlign">Align</a> <br>
+               </strong><em> When selected, the associated alignment will be used to
+               superimpose all the structures in the view onto the first structure in
+               the alignment. The regions used to calculate the superposition will be
+               highlighted using the 'Cartoon' rendering style, and the remaining
+               data shown as a chain trace.<br></em></li>
+       </ul>
+       </li>
+       <li><strong>Help<br>
+       </strong>
+       <ul>
+               <li><strong>Chimera Help<br>
+               </strong><em>Access the Chimera Help documentation in a new browser window.</em></li>
+       </ul>
+       </li>
+</ul>
+</p>
+</body>
+</html>
index 5102679..45e5526 100644 (file)
@@ -79,7 +79,7 @@ atoms in the displayed structures.</p>
 and alpha carbon location. Double clicking an atom allows distances to
 be measured from it to any other atom in the structure.</p>
 <p>
-<table>
+<table border="1">
        <tr>
                <td><strong>Action</strong></td>
                <td><strong>Windows</strong></td>
@@ -162,7 +162,7 @@ be measured from it to any other atom in the structure.</p>
     <li><strong>Select all views<br></strong><em>This is only enabled when </em><strong>Select many views</strong><em> is also enabled, and will add all associated views to the set used to colour the structure display.</em>
   </li>
     <li><strong>Invert selection<br></strong><em>This is only enabled when </em><strong>Select many views</strong><em> is also enabled, and will replace the current set of views with any remaining views not currently used to colour the structure display.</em>
-  </li></ul></li>
+  </li></ul></li></ul>
        <li><strong>Colours<br>
        </strong>
        <ul>
index 1831c3e..b2d8b93 100755 (executable)
@@ -121,6 +121,8 @@ annotation will be shown on the alignment when available.
 <p><em>Add Temperature Factor annotation to alignment</em> - if selected, PDB Temperature Factor
 annotation will be shown on the alignment when available. 
 <p><em>Default structure viewer</em> - choose JMOL or CHIMERA for viewing 3D structures. 
+<p><em>Path to Chimera program</em> - Optional, as Jalview will search standard installation paths for Windows, Linux or MacOS. 
+If you have installed Chimera in a non-standard location, you can specify it here. Enter the full path to the Chimera executable program.  
 
 <p><a name="connections"><strong>&quot;Connections&quot;
 Preferences tab</strong></a></p>
index 1f49498..8fc557e 100755 (executable)
@@ -28,6 +28,9 @@
 <p>Jalview can view protein structures associated with a sequence
 via the <strong>"Structure&rarr;"</strong> submenu from a
 sequence's <a href="../menus/popupMenu.html">pop-up menu</a>.</p>
+A <a href="jmol.html">Jmol viewer</a> has been included since Jalview 2.3. Jalview 2.8.2 added support for <a href="https://www.cgl.ucsf.edu/chimera/">Chimera</a>,
+provided this has been separately installed. Choice of default viewer is configurable in the Preferences <a href="preferences.html#structure">Structure tab</a>. 
+  
 <p>The following menu entries are provided for viewing structure data<br>
   <ul>
     <li>The <strong>&quot;Structure&#8594;View
@@ -40,14 +43,13 @@ sequence's <a href="../menus/popupMenu.html">pop-up menu</a>.</p>
       with the current selection, superposed according to the currently selected region of the alignment.<br/><em>This
       capability was added in Jalview 2.7</em>
     </li>
-    <li><a name="viewreps"/>The <strong>&quot;Structure&#8594;View all <em>N</em>
+    <li>The <strong>&quot;Structure&#8594;View all <em>N</em>
         representative structures
     </strong> option will open a new window containing exactly one structure per
       currently selected sequence.<br />
     <em>The View representative structures option was introduced in
         Jalview 2.8.1</em></li>
   </ul>
-  <br> 
 </p>
 
 <p>If a single pdb
@@ -55,19 +57,19 @@ structure is selected, one of the following will happen:</p>
 
 <ul>
        <li>If no structures are open, then an interactive display of the
-       structure will be opened in a new window</li>
+       structure will be opened in a new window.</li>
 
        <li>If another structure is already shown for the current
        alignment, then you will be asked if you want to add and <a
                href="jmol.html#align">align this structure</a> to the structure in
-       the existing view. (<em>new feature in Jalview 2.6</em>)</li>
+       the existing view. (<em>new feature in Jalview 2.6</em>).</li>
 
        <li>If the structure is already shown, then you will be prompted
        to associate the sequence with an existing view of the selected
        structure. This is useful when working with multi-domain or multi-chain PDB files.</li>
 
        <li style="list-style: none">See the <a href="jmol.html">Jmol
-       PDB viewer</a> help page for more information about the display.</li>
+       </a> and <a href="chimera.html">Chimera</a> PDB viewer help pages for more information about the display.</li>
 </ul>
        <p><strong>Associating PDB files with Sequences</strong></p>
        <p>To associate PDB files with a sequence, right click on a sequence
index a2db06d..511e5e9 100644 (file)
@@ -248,6 +248,9 @@ label.use_rnaview = Use RNAView for secondary structure
 label.autoadd_secstr = Add secondary structure annotation to alignment
 label.autoadd_temp = Add Temperature Factor annotation to alignment
 label.structure_viewer = Default structure viewer
+label.chimera_path = Path to Chimera program
+label.chimera_path_tip = Jalview will try standard locations, plus any path entered here.
+label.invalid_path = File not found or not executable
 label.min_colour = Minimum Colour
 label.max_colour = Maximum Colour
 label.use_original_colours = Use Original Colours
@@ -383,7 +386,7 @@ label.pdb_entry_is_already_displayed = {0} is already displayed.\nDo you want to
 label.map_sequences_to_visible_window = Map Sequences to Visible Window: {0}
 label.add_pdbentry_to_view = Do you want to add {0} to the view called\n{1}\n
 label.align_to_existing_structure_view = Align to existing structure view
-label.pdb_entries_couldnt_be_retrieved = The following pdb entries could not be retrieved from the PDB\:\n{0}\nPlease try downloading them manually.
+label.pdb_entries_couldnt_be_retrieved = The following pdb entries could not be retrieved from the PDB\:\n{0}\nPlease retry, or try downloading them manually.
 label.couldnt_load_file = Couldn't load file
 label.couldnt_find_pdb_id_in_file = Couldn't find a PDB id in the file supplied. Please enter an Id to identify this structure.
 label.no_pdb_id_in_file = No PDB Id in File
@@ -485,6 +488,10 @@ label.edit_sequence = Edit Sequence
 label.edit_sequences = Edit Sequences
 label.sequence_details = Sequence Details
 label.jmol_help = Jmol Help
+label.chimera_help = Chimera Help
+label.close_viewer = Close Viewer
+label.confirm_close_chimera = This will close Jalview''s connection to {0}.<br>Do you want to close the Chimera window as well?
+label.chimera_help = Chimera Help
 label.all = All
 label.sort_by = Sort alignment by
 label.sort_by_score = Sort by Score
@@ -512,7 +519,7 @@ label.toggle_absolute_relative_display_threshold = Toggle between absolute and r
 label.display_features_same_type_different_label_using_different_colour = Display features of the same type with a different label using a different colour. (e.g. domain features)
 label.select_colour_minimum_value = Select Colour for Minimum Value
 label.select_colour_maximum_value = Select Colour for Maximum Value
-label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment = Open a new Jmol view with all structures associated with the current selection and superimpose them using the alignment.
+label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment = Open a new structure viewer with all structures associated with the current selection and superimpose them using the alignment.
 label.open_url_param = Open URL {0}
 label.open_url_seqs_param = Open URL ({0}..) ({1} seqs)
 label.load_pdb_file_associate_with_sequence = Load a PDB file and associate it with sequence {0}
@@ -601,6 +608,7 @@ label.das_settings = DAS Settings
 label.web_services = Web Services
 label.right_click_to_edit_currently_selected_parameter = Right click to edit currently selected parameter.
 label.let_jmol_manage_structure_colours = Let Jmol manage structure colours
+label.let_chimera_manage_structure_colours = Let Chimera manage structure colours
 label.marks_leaves_tree_not_associated_with_sequence = Marks leaves of tree not associated with a sequence
 label.index_web_services_menu_by_host_site = Index web services in menu by the host site
 label.option_want_informed_web_service_URL_cannot_be_accessed_jalview_when_starts_up = Check this option if you want to be informed<br>when a web service URL cannot be accessed by Jalview<br>when it starts up
@@ -649,7 +657,7 @@ label.edit_name_and_description_current_group = Edit name and description of cur
 label.view_structure_for = View structure for {0}
 label.view_all_structures = View all {0} structures.
 label.view_all_representative_structures = View all {0} representative structures.
-label.open_new_jmol_view_with_all_representative_structures_associated_current_selection_superimpose_using_alignment = Opens a new Jmol view with all representative structures\nassociated with the current selection\nsuperimposed with the current alignment.
+label.open_new_jmol_view_with_all_representative_structures_associated_current_selection_superimpose_using_alignment = Opens a new structure viewer with all representative structures\nassociated with the current selection\nsuperimposed with the current alignment.
 label.associate_structure_with_sequence = Associate Structure with Sequence
 label.from_file = from file
 label.enter_pdb_id = Enter PDB Id
@@ -695,8 +703,10 @@ label.jalview_pca_calculation = Jalview PCA Calculation
 label.link_name = Link Name
 label.pdb_file = PDB file
 label.colour_with_jmol = Colour with Jmol
+label.colour_with_chimera = Colour with Chimera
 label.align_structures = Align structures
 label.jmol = Jmol
+label.chimera = Chimera
 label.sort_alignment_by_tree = Sort Alignment By Tree
 label.mark_unlinked_leaves = Mark Unlinked Leaves
 label.associate_leaves_with = Associate Leaves With
@@ -836,7 +846,7 @@ label.service_url = Service URL
 label.copied_sequences = Copied sequences
 label.cut_sequences = Cut Sequences
 label.conservation_colour_increment = Conservation Colour Increment ({0})
-label.percentage_identity_thereshold = Percentage Identity Thereshold ({0})
+label.percentage_identity_thereshold = Percentage Identity Threshold ({0})
 label.error_unsupported_owwner_user_colour_scheme = Unsupported owner for User Colour scheme dialog
 label.save_alignment_to_file = Save Alignment to file
 label.save_features_to_file = Save Features to File
@@ -1141,7 +1151,7 @@ label.edit_jabaws_url = Edit JABAWS URL
 label.add_jabaws_url = Add new JABAWS URL
 label.news_from_jalview = News from http://www.jalview.org
 label.cut_paste_alignmen_file = Cut & Paste Alignment File
-label.enter_redundancy_thereshold = Enter the redundancy thereshold
+label.enter_redundancy_thereshold = Enter the redundancy threshold
 label.select_dark_light_set_thereshold = <html><i>Select a dark and light text colour, then set the threshold to<br>switch between colours, based on background colour</i></html>
 label.select_feature_colour = Select Feature Colour
 label.delete_all = Delete all sequences
index c0b3a39..a7440e7 100644 (file)
@@ -152,6 +152,20 @@ public class ChimeraManager
 
   public List<ChimeraModel> openModel(String modelPath, ModelType type)
   {
+    return openModel(modelPath, getFileNameFromPath(modelPath), type);
+  }
+
+  /**
+   * Overloaded method to allow Jalview to pass in a model name.
+   * 
+   * @param modelPath
+   * @param modelName
+   * @param type
+   * @return
+   */
+  public List<ChimeraModel> openModel(String modelPath, String modelName,
+          ModelType type)
+  {
     logger.info("chimera open " + modelPath);
     stopListening();
     List<String> response = null;
@@ -190,22 +204,14 @@ public class ChimeraManager
             {
               continue;
             }
-            String modelName = modelPath;
-            // TODO: [Optional] Convert path to name in a better way
-            if (modelPath.lastIndexOf(File.separator) > 0)
-            {
-              modelName = modelPath.substring(modelPath
-                      .lastIndexOf(File.separator) + 1);
-            }
-            else if (modelPath.lastIndexOf("/") > 0)
-            {
-              modelName = modelPath
-                      .substring(modelPath.lastIndexOf("/") + 1);
-            }
             ChimeraModel newModel = new ChimeraModel(modelName, type,
                     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;
           }
         }
@@ -265,6 +271,34 @@ public class ChimeraManager
     return models;
   }
 
+  /**
+   * Refactored method to extract the last (or only) element delimited by file
+   * path separator.
+   * 
+   * @param modelPath
+   * @return
+   */
+  private String getFileNameFromPath(String modelPath)
+  {
+    String modelName = modelPath;
+    if (modelPath == null)
+    {
+      return null;
+    }
+    // TODO: [Optional] Convert path to name in a better way
+    if (modelPath.lastIndexOf(File.separator) > 0)
+    {
+      modelName = modelPath.substring(modelPath
+              .lastIndexOf(File.separator) + 1);
+    }
+    else if (modelPath.lastIndexOf("/") > 0)
+    {
+      modelName = modelPath
+              .substring(modelPath.lastIndexOf("/") + 1);
+    }
+    return modelName;
+  }
+
   public void closeModel(ChimeraModel model)
   {
     // int model = structure.modelNumber();
@@ -450,14 +484,20 @@ public class ChimeraManager
 
   public boolean isChimeraLaunched()
   {
-    // TODO: [Optional] What is the best way to test if chimera is launched?
-
-    // sendChimeraCommand("test", true) !=null
+    boolean launched = false;
     if (chimera != null)
     {
-      return true;
+      try
+      {
+        chimera.exitValue();
+        // if we get here, process has ended
+      } catch (IllegalThreadStateException e)
+      {
+        // ok - not yet terminated
+        launched = true;
+      }
     }
-    return false;
+    return launched;
   }
 
   public boolean launchChimera(List<String> chimeraPaths)
@@ -533,7 +573,7 @@ public class ChimeraManager
     {
       return null;
     }
-    return ChimUtils.parseModelColor((String) colorLines.get(0));
+    return ChimUtils.parseModelColor(colorLines.get(0));
   }
 
   /**
@@ -647,6 +687,7 @@ public class ChimeraManager
     {
       return null;
     }
+    // TODO do we need a maximum wait time before aborting?
     while (busy)
     {
       try
@@ -658,32 +699,38 @@ public class ChimeraManager
       ;
     }
     busy = true;
-    chimeraListenerThreads.clearResponse(command);
-    String text = command.concat("\n");
-    // System.out.println("send command to chimera: " + text);
     try
     {
-      // send the command
-      chimera.getOutputStream().write(text.getBytes());
-      chimera.getOutputStream().flush();
-    } catch (IOException e)
-    {
-      // logger.info("Unable to execute command: " + text);
-      // logger.info("Exiting...");
-      logger.warn("Unable to execute command: " + text);
-      logger.warn("Exiting...");
-      clearOnChimeraExit();
-      busy = false;
-      return null;
-    }
-    if (!reply)
+      chimeraListenerThreads.clearResponse(command);
+      String text = command.concat("\n");
+      // System.out.println("send command to chimera: " + text);
+      try
+      {
+        // send the command
+        chimera.getOutputStream().write(text.getBytes());
+        chimera.getOutputStream().flush();
+      } catch (IOException e)
+      {
+        // logger.info("Unable to execute command: " + text);
+        // logger.info("Exiting...");
+        logger.warn("Unable to execute command: " + text);
+        logger.warn("Exiting...");
+        clearOnChimeraExit();
+        // busy = false;
+        return null;
+      }
+      if (!reply)
+      {
+        // busy = false;
+        return null;
+      }
+      List<String> rsp = chimeraListenerThreads.getResponse(command);
+      // busy = false;
+      return rsp;
+    } finally
     {
       busy = false;
-      return null;
     }
-    List<String> rsp = chimeraListenerThreads.getResponse(command);
-    busy = false;
-    return rsp;
   }
 
   public StructureManager getStructureManager()
index ec956d7..1208638 100644 (file)
@@ -1,12 +1,14 @@
 package ext.edu.ucsf.rbvi.strucviz2;
 
+import jalview.bin.Cache;
+import jalview.gui.Preferences;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -32,10 +34,6 @@ public class StructureManager
   static final String[] defaultResidueKeys =
   { "FunctionalResidues", "ResidueList", "Residues" };
 
-  private final String chimeraPropertyName = "chimera";
-
-  private final String chimeraPathPropertyKey = "LastChimeraPath";
-
   public enum ModelType
   {
     PDB_MODEL, MODBASE_MODEL, SMILES
@@ -494,7 +492,9 @@ public class StructureManager
       // we do not care about the model anymore
       selSpec = selSpec.concat(nodeInfo.toSpec());
       if (i < chimSelectionList.size() - 1)
+      {
         selSpec.concat("|");
+      }
     }
     if (selSpec.length() > 0)
     {
@@ -665,7 +665,9 @@ public class StructureManager
     for (ChimeraStructuralObject cso : chimSelectionList)
     {
       if (cso != null)
+      {
         cso.setSelected(false);
+      }
     }
     chimSelectionList.clear();
   }
@@ -879,17 +881,16 @@ public class StructureManager
       }
     }
 
-    // if no network settings, check if the last chimera path is saved in the
-    // session
-    // String lastPath = CytoUtils.getDefaultChimeraPath(registrar,
-    // chimeraPropertyName,
-    // chimeraPathPropertyKey);
-    // if (lastPath != null && !lastPath.equals("")) {
-    // pathList.add(lastPath);
-    // return pathList;
-    // }
+    /*
+     * Jalview addition: check if path set in user preferences.
+     */
+    String userPath = Cache.getDefault(Preferences.CHIMERA_PATH, null);
+    if (userPath != null)
+    {
+      pathList.add(userPath);
+    }
 
-    // if no user settings and no last path, get default system's settings
+    // Add default installation paths
     String os = System.getProperty("os.name");
     if (os.startsWith("Linux"))
     {
index dee027b..883d536 100644 (file)
@@ -12,7 +12,7 @@ import java.util.Map;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import ext.edu.ucsf.rbvi.strucviz2.*;
+import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
 
 /***************************************************
  *                 Thread Classes                  *
@@ -67,6 +67,7 @@ public class ListenerThreads extends Thread {
        public List<String> getResponse(String command) {
                List<String> reply;
                // System.out.println("getResponse: "+command);
+    // TODO do we need a maximum wait time before aborting?
                while (!replyLog.containsKey(command)) {
                        try {
                                Thread.currentThread().sleep(100);
@@ -88,7 +89,9 @@ public class ListenerThreads extends Thread {
                } catch (InterruptedException e) {
                }
                if (replyLog.containsKey(command))
-                       replyLog.remove(command);
+    {
+      replyLog.remove(command);
+    }
                return;
        }
 
@@ -99,7 +102,9 @@ public class ListenerThreads extends Thread {
         */
        private void chimeraRead() throws IOException {
                if (chimera == null)
-                       return;
+    {
+      return;
+    }
 
                String line = null;
                while ((line = lineReader.readLine()) != null) {
@@ -153,9 +158,13 @@ public class ListenerThreads extends Thread {
                        replyLog.put(command, reply);
                }
                if (updateModels)
-                       (new ModelUpdater()).start();
+    {
+      (new ModelUpdater()).start();
+    }
                if (updateSelection)
-                       (new SelectionUpdater()).start();
+    {
+      (new SelectionUpdater()).start();
+    }
                if (importNetwork) {
                        (new NetworkUpdater(line)).start();
                }
index a48b750..24ed1b4 100755 (executable)
@@ -173,6 +173,7 @@ import org.apache.log4j.SimpleLayout;
  * display</li>
  * <li>STRUCTURE_DISPLAY choose from JMOL (default) or CHIMERA for 3D structure
  * display</li>
+ * <li>CHIMERA_PATH specify full path to Chimera program (if non-standard)</li>
  * 
  * </ul>
  * Deprecated settings:
@@ -906,4 +907,27 @@ public class Cache
     }
     return sourceRegistry;
   }
+
+  /**
+   * Set the specified value, or remove it if null or empty. Does not save the
+   * properties file.
+   * 
+   * @param propName
+   * @param value
+   */
+  public static void setOrRemove(String propName, String value)
+  {
+    if (propName == null)
+    {
+      return;
+    }
+    if (value == null || value.trim().length() < 1)
+    {
+      Cache.applicationProperties.remove(propName);
+    }
+    else
+    {
+      Cache.applicationProperties.setProperty(propName, value);
+    }
+  }
 }
index a39f355..090b61d 100644 (file)
@@ -44,10 +44,9 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Hashtable;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Vector;
 
 import ext.edu.ucsf.rbvi.strucviz2.ChimeraManager;
 import ext.edu.ucsf.rbvi.strucviz2.ChimeraModel;
@@ -59,6 +58,10 @@ public abstract class JalviewChimeraBinding extends
         SequenceStructureBinding, StructureSelectionManagerProvider
 
 {
+  private static final String PHOSPHORUS = "P";
+
+  private static final String ALPHACARBON = "CA";
+
   private StructureManager csm;
 
   private ChimeraManager viewer;
@@ -71,13 +74,14 @@ public abstract class JalviewChimeraBinding extends
   private boolean loadingFromArchive = false;
 
   /**
-   * second flag to indicate if the jmol viewer should ignore sequence colouring
-   * events from the structure manager because the GUI is still setting up
+   * second 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 Jmol viewer's paint method can be called
+   * state flag used to check if the Chimera viewer's paint method can be called
    */
   private boolean finishedInit = false;
 
@@ -95,18 +99,18 @@ public abstract class JalviewChimeraBinding extends
 
   /**
    * when true, try to search the associated datamodel for sequences that are
-   * associated with any unknown structures in the Jmol view.
+   * associated with any unknown structures in the Chimera view.
    */
   private boolean associateNewStructs = false;
 
-  Vector atomsPicked = new Vector();
+  List<String> atomsPicked = new ArrayList<String>();
 
-  public Vector chainNames;
+  public List<String> chainNames;
 
-  Hashtable chainFile;
+  private Map<String, String> chainFile;
 
   /**
-   * array of target chains for seuqences - tied to pdbentry and sequence[]
+   * array of target chains for sequences - tied to pdbentry and sequence[]
    */
   protected String[][] chains;
 
@@ -116,7 +120,7 @@ public abstract class JalviewChimeraBinding extends
 
   public String fileLoadingError;
 
-  private Map<String, List<ChimeraModel>> chimmaps = new HashMap<String, List<ChimeraModel>>();
+  private Map<String, List<ChimeraModel>> chimmaps = new LinkedHashMap<String, List<ChimeraModel>>();
 
   private List<String> mdlToFile = new ArrayList<String>();
 
@@ -138,7 +142,7 @@ public abstract class JalviewChimeraBinding extends
     try
     {
       List<ChimeraModel> oldList = viewer.getModelList();
-      viewer.openModel(file, ModelType.PDB_MODEL);
+      viewer.openModel(file, pe.getId(), ModelType.PDB_MODEL);
       List<ChimeraModel> newList = viewer.getModelList();
       if (oldList.size() < newList.size())
       {
@@ -170,7 +174,7 @@ public abstract class JalviewChimeraBinding extends
         } catch (Error e)
         {
         }
-        // Explicitly map to the filename used by Jmol ;
+        // Explicitly map to the filename used by Chimera ;
         // pdbentry[pe].getFile(), protocol);
 
         if (ssm != null)
@@ -233,13 +237,6 @@ public abstract class JalviewChimeraBinding extends
     }
     viewer = new ChimeraManager(
             csm = new ext.edu.ucsf.rbvi.strucviz2.StructureManager(true));
-    /*
-     * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
-     * "jalviewJmol", ap.av.applet .getDocumentBase(),
-     * ap.av.applet.getCodeBase(), "", this);
-     * 
-     * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
-     */
   }
 
   public JalviewChimeraBinding(StructureSelectionManager ssm,
@@ -251,12 +248,13 @@ public abstract class JalviewChimeraBinding extends
   }
 
   /**
-   * construct a title string for the viewer window based on the data jalview
+   * Construct a title string for the viewer window based on the data Jalview
    * knows about
    * 
+   * @param verbose
    * @return
    */
-  public String getViewerTitle()
+  public String getViewerTitle(boolean verbose)
   {
     if (sequence == null || pdbentry == null || sequence.length < 1
             || pdbentry.length < 1 || sequence[0].length < 1)
@@ -265,20 +263,24 @@ public abstract class JalviewChimeraBinding extends
     }
     // TODO: give a more informative title when multiple structures are
     // displayed.
-    StringBuffer title = new StringBuffer("Chimera view for "
-            + sequence[0][0].getName() + ":" + pdbentry[0].getId());
+    StringBuilder title = new StringBuilder(64);
+    title.append("Chimera view for " + sequence[0][0].getName() + ":"
+            + pdbentry[0].getId());
 
-    if (pdbentry[0].getProperty() != null)
+    if (verbose)
     {
-      if (pdbentry[0].getProperty().get("method") != null)
-      {
-        title.append(" Method: ");
-        title.append(pdbentry[0].getProperty().get("method"));
-      }
-      if (pdbentry[0].getProperty().get("chains") != null)
+      if (pdbentry[0].getProperty() != null)
       {
-        title.append(" Chain:");
-        title.append(pdbentry[0].getProperty().get("chains"));
+        if (pdbentry[0].getProperty().get("method") != null)
+        {
+          title.append(" Method: ");
+          title.append(pdbentry[0].getProperty().get("method"));
+        }
+        if (pdbentry[0].getProperty().get("chains") != null)
+        {
+          title.append(" Chain:");
+          title.append(pdbentry[0].getProperty().get("chains"));
+        }
       }
     }
     return title.toString();
@@ -288,47 +290,52 @@ public abstract class JalviewChimeraBinding extends
    * prepare the view for a given set of models/chains. chainList contains
    * strings of the form 'pdbfilename:Chaincode'
    * 
-   * @param chainList
+   * @param toshow
    *          list of chains to make visible
    */
-  public void centerViewer(Vector chainList)
+  public void centerViewer(List<String> toshow)
   {
-    StringBuffer cmd = new StringBuffer();
-    String lbl;
+    StringBuilder cmd = new StringBuilder(64);
     int mlength, p;
-    for (int i = 0, iSize = chainList.size(); i < iSize; i++)
+    for (String lbl : toshow)
     {
       mlength = 0;
-      lbl = (String) chainList.elementAt(i);
       do
       {
         p = mlength;
         mlength = lbl.indexOf(":", p);
       } while (p < mlength && mlength < (lbl.length() - 2));
       // TODO: lookup each pdb id and recover proper model number for it.
-      cmd.append("#" + getModelNum((String) chainFile.get(lbl)) + "."
+      cmd.append("#" + getModelNum(chainFile.get(lbl)) + "."
               + lbl.substring(mlength + 1) + " or ");
     }
     if (cmd.length() > 0)
+    {
       cmd.setLength(cmd.length() - 4);
-    evalStateCommand("~display #*; ~ribbon #*; ribbon " + cmd + ";focus "
-            + cmd,false);
+    }
+    String cmdstring = cmd.toString();
+    evalStateCommand("~display #*; ~ribbon #*; ribbon " + cmdstring
+            + ";focus " + cmdstring, false);
   }
 
-  public void closeViewer()
+  /**
+   * Close down the Jalview viewer, and (optionally) the associate Chimera
+   * window.
+   */
+  public void closeViewer(boolean closeChimera)
   {
     ssm.removeStructureViewerListener(this, this.getPdbFile());
-    // and shut down Chimera
-    viewer.exitChimera();
-    // viewer.evalStringQuiet("zap");
-    // viewer.setJmolStatusListener(null);
+    if (closeChimera)
+    {
+      viewer.exitChimera();
+    }
     lastCommand = null;
     viewer = null;
     releaseUIResources();
   }
 
   /**
-   * called by JalviewJmolbinding after closeViewer is called - release any
+   * called by JalviewChimerabinding after closeViewer is called - release any
    * resources and references so they can be garbage collected.
    */
   protected abstract void releaseUIResources();
@@ -336,17 +343,16 @@ public abstract class JalviewChimeraBinding extends
   public void colourByChain()
   {
     colourBySequence = false;
-    // TODO: colour by chain should colour each chain distinctly across all
-    // visible models
-    // TODO: http://issues.jalview.org/browse/JAL-628
+    // this is not a valid Chimera command; is there one? Menu option hidden
     evalStateCommand("select *;color chain",false);
   }
 
   public void colourByCharge()
   {
     colourBySequence = false;
-    evalStateCommand("colour *;color white;select ASP,GLU;color red;"
-            + "select LYS,ARG;color blue;select CYS;color yellow", false);
+    evalStateCommand(
+            "color white;color red ::ASP;color red ::GLU;color blue ::LYS;color blue ::ARG;color yellow ::CYS",
+            false);
   }
 
   /**
@@ -394,9 +400,9 @@ public abstract class JalviewChimeraBinding extends
           int[] _refStructure, ColumnSelection[] _hiddenCols)
   {
     assert (_alignment.length == _refStructure.length && _alignment.length != _hiddenCols.length);
-    StringBuffer allComs = new StringBuffer(); // whole shebang for superposition
+    StringBuilder allComs = new StringBuilder(128); // Chimera superposition cmd
     String[] files = getPdbFile();
-    // check to see if we are still waiting for Jmol files
+    // check to see if we are still waiting for Chimera files
     long starttime = System.currentTimeMillis();
     boolean waiting = true;
     do
@@ -427,7 +433,7 @@ public abstract class JalviewChimeraBinding extends
     if (waiting)
     {
       System.err
-              .println("RUNTIME PROBLEM: Jmol seems to be taking a long time to process all the structures.");
+              .println("RUNTIME PROBLEM: Chimera seems to be taking a long time to process all the structures.");
       return;
     }
     refreshPdbEntries();
@@ -455,7 +461,6 @@ public abstract class JalviewChimeraBinding extends
       {
         refStructure = -1;
       }
-      StringBuffer command = new StringBuffer();
 
       boolean matched[] = new boolean[alignment.getWidth()];
       for (int m = 0; m < matched.length; m++)
@@ -466,10 +471,9 @@ public abstract class JalviewChimeraBinding extends
 
       int commonrpositions[][] = new int[files.length][alignment.getWidth()];
       String isel[] = new String[files.length];
-      // reference structure - all others are superposed in it
       String[] targetC = new String[files.length];
       String[] chainNames = new String[files.length];
-      String[] atomS = new String[files.length];
+      String[] atomSpec = new String[files.length];
       for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
       {
         StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
@@ -536,7 +540,7 @@ public abstract class JalviewChimeraBinding extends
               }
               chainNames[pdbfnum] = mapping[m].getPdbId()
                       + targetC[pdbfnum];
-              atomS[pdbfnum] = asp.getRNA()!=null ? "P" : "CA";
+              atomSpec[pdbfnum] = asp.getRNA() != null ? PHOSPHORUS : ALPHACARBON;
               // move on to next pdb file
               s = sequence[pdbfnum].length;
               break;
@@ -619,6 +623,7 @@ public abstract class JalviewChimeraBinding extends
           }
         }
       }
+      StringBuilder command = new StringBuilder(256);
       for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
       {
         if (pdbfnum == refStructure || selcom[pdbfnum] == null
@@ -626,23 +631,31 @@ public abstract class JalviewChimeraBinding extends
         {
           continue;
         }
-        if (command.length()>0)
+        if (command.length() > 0)
         {
           command.append(";");
         }
-        command.append("match");
 
-        // form the matched pair strings
-        for (int s = 0; s < 2; s++)
-        {
-          command.append(" #"+(s == 0 ? pdbfnum : refStructure)+".1");
-          // note - need to select on first model, otherwise it all goes wrong!
-          command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
-          command.append("@"+atomS[(s == 0 ? pdbfnum : refStructure)]); // match on backbone alpha/polyphosphate
-        }
+        /*
+         * Form Chimera match command, from the 'new' structure to the
+         * 'reference' structure e.g. (residues 1-91, chain B/A, alphacarbons):
+         * 
+         * match #1:1-91.B@CA #0:1-91.A@CA
+         * 
+         * @see
+         * https://www.cgl.ucsf.edu/chimera/docs/UsersGuide/midas/match.html
+         */
+        command.append("match #" + pdbfnum /* +".1" */);
+        // TODO: handle sub-models
+        command.append(selcom[pdbfnum]);
+        command.append("@" + atomSpec[pdbfnum]);
+        command.append(" #" + refStructure /* +".1" */);
+        command.append(selcom[refStructure]);
+        command.append("@" + atomSpec[refStructure]);
       }
       if (selectioncom.length() > 0)
       {
+        // TODO remove debug output
         System.out.println("Select regions:\n" + selectioncom.toString());
         System.out
                 .println("Superimpose command(s):\n" + command.toString());
@@ -659,9 +672,9 @@ public abstract class JalviewChimeraBinding extends
       }
       System.out.println("Select regions:\n" + selectioncom.toString());
       allComs.append("; ~display all; chain @CA|P; ribbon "
-              + selectioncom.toString() + "");
+              + selectioncom.toString() + "; focus");
       // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
-      evalStateCommand(allComs.toString(),false);
+      evalStateCommand(allComs.toString(), true /* false */);
     }
     
   }
@@ -678,7 +691,24 @@ public abstract class JalviewChimeraBinding extends
     }
   }
 
-  public void evalStateCommand(final String command, boolean resp)
+  /**
+   * Answers true if the Chimera process is still running, false if ended or not
+   * started.
+   * 
+   * @return
+   */
+  public boolean isChimeraRunning()
+  {
+    return viewer.isChimeraLaunched();
+  }
+
+  /**
+   * Send a command to Chimera, and optionally log any responses.
+   * 
+   * @param command
+   * @param logResponse
+   */
+  public void evalStateCommand(final String command, boolean logResponse)
   {
     viewerCommandHistory(false);
     checkLaunched();
@@ -689,8 +719,9 @@ public abstract class JalviewChimeraBinding extends
 //        @Override
 //        public void run()
 //        {
-          lastReply = viewer.sendChimeraCommand(command, resp);
-          if (debug)
+      // 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);
@@ -719,7 +750,9 @@ public abstract class JalviewChimeraBinding extends
           jalview.api.AlignmentViewPanel alignmentv)
   {
     if (!colourBySequence || !loadingFinished)
+    {
       return;
+    }
     if (ssm == null)
     {
       return;
@@ -738,12 +771,14 @@ public abstract class JalviewChimeraBinding extends
     for (jalview.structure.StructureMappingcommandSet cpdbbyseq : ChimeraCommands
             .getColourBySequenceCommand(ssm, files, sequence, sr, fr,
                     alignment))
+    {
       for (String cbyseq : cpdbbyseq.commands)
       {
         waitForChimera();
         evalStateCommand(cbyseq, false);
         waitForChimera();
       }
+    }
   }
 
   private void waitForChimera()
@@ -767,25 +802,6 @@ public abstract class JalviewChimeraBinding extends
     this.colourBySequence = colourBySequence;
   }
 
-  public void createImage(String file, String type, int quality)
-  {
-    System.out.println("JMOL CREATE IMAGE");
-  }
-
-  public String createImage(String fileName, String type,
-          Object textOrBytes, int quality)
-  {
-    System.out.println("JMOL CREATE IMAGE");
-    return null;
-  }
-
-  public String eval(String strEval)
-  {
-    // System.out.println(strEval);
-    // "# 'eval' is implemented only for the applet.";
-    return null;
-  }
-
   // End StructureListener
   // //////////////////////////
 
@@ -804,7 +820,9 @@ public abstract class JalviewChimeraBinding extends
           String pdbfile)
   {
     if (getModelNum(pdbfile) < 0)
+    {
       return null;
+    }
     log("get model / residue colour attribute unimplemented");
     return null;
   }
@@ -837,7 +855,9 @@ public abstract class JalviewChimeraBinding extends
     for (int i = 0; i < mfn.length; i++)
     {
       if (mfn[i].equalsIgnoreCase(modelFileName))
+      {
         return i;
+      }
     }
     return -1;
   }
@@ -996,8 +1016,10 @@ public abstract class JalviewChimeraBinding extends
     String chainId;
 
     if (strInfo.indexOf(":") > -1)
+    {
       chainId = strInfo.substring(strInfo.indexOf(":") + 1,
               strInfo.indexOf("."));
+    }
     else
     {
       chainId = " ";
@@ -1035,7 +1057,9 @@ public abstract class JalviewChimeraBinding extends
       ;
     }
     if (lastMessage == null || !lastMessage.equals(strInfo))
+    {
       ssm.mouseOverStructure(pdbResNum, chainId, pdbfilename);
+    }
 
     lastMessage = strInfo;
   }
@@ -1054,13 +1078,17 @@ public abstract class JalviewChimeraBinding extends
     int chainSeparator = strInfo.indexOf(":");
     int p = 0;
     if (chainSeparator == -1)
+    {
       chainSeparator = strInfo.indexOf(".");
+    }
 
     String picked = strInfo.substring(strInfo.indexOf("]") + 1,
             chainSeparator);
     String mdlString = "";
     if ((p = strInfo.indexOf(":")) > -1)
+    {
       picked += strInfo.substring(p + 1, strInfo.indexOf("."));
+    }
 
     if ((p = strInfo.indexOf("/")) > -1)
     {
@@ -1073,12 +1101,12 @@ public abstract class JalviewChimeraBinding extends
     if (!atomsPicked.contains(picked))
     {
       viewer.select(picked);
-      atomsPicked.addElement(picked);
+      atomsPicked.add(picked);
     }
     else
     {
       viewer.select("not " + picked);
-      atomsPicked.removeElement(picked);
+      atomsPicked.remove(picked);
     }
     viewerCommandHistory(true);
     // TODO: in application this happens
@@ -1093,7 +1121,7 @@ public abstract class JalviewChimeraBinding extends
 
   // incremented every time a load notification is successfully handled -
   // lightweight mechanism for other threads to detect when they can start
-  // referrring to new structures.
+  // referring to new structures.
   private long loadNotifiesHandled = 0;
 
   public long getLoadNotifiesHandled()
@@ -1119,8 +1147,8 @@ public abstract class JalviewChimeraBinding extends
     fileLoadingError = null;
     String[] oldmodels = modelFileNames;
     modelFileNames = null;
-    chainNames = new Vector();
-    chainFile = new Hashtable();
+    chainNames = new ArrayList<String>();
+    chainFile = new HashMap<String, String>();
     boolean notifyLoaded = false;
     String[] modelfilenames = getPdbFile();
     // first check if we've lost any structures
@@ -1181,49 +1209,43 @@ public abstract class JalviewChimeraBinding extends
     colourBySequence = false;
 
     if (cs == null)
+    {
       return;
+    }
 
     String res;
     int index;
     Color col;
+    // Chimera expects RBG values in the range 0-1
+    final double normalise = 255D;
     viewerCommandHistory(false);
     // TODO: Switch between nucleotide or aa selection expressions
     Enumeration en = ResidueProperties.aa3Hash.keys();
-    StringBuffer command = new StringBuffer("select *;color white;");
+    StringBuilder command = new StringBuilder(128);
+    command.append("color white;");
     while (en.hasMoreElements())
     {
       res = en.nextElement().toString();
       index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue();
       if (index > 20)
+      {
         continue;
+      }
 
       col = cs.findColour(ResidueProperties.aa[index].charAt(0));
-      // TODO: need colour string function and res selection here
-      command.append("select " + res + ";color[" + col.getRed() + ","
-              + col.getGreen() + "," + col.getBlue() + "];");
+      command.append("color " + col.getRed() / normalise + ","
+              + col.getGreen() / normalise + "," + col.getBlue()
+              / normalise + " ::" + res + ";");
     }
 
     evalStateCommand(command.toString(),false);
     viewerCommandHistory(true);
   }
 
-  public void showHelp()
-  {
-    // chimera help
-    showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
-  }
-
   /**
-   * open the URL somehow
-   * 
-   * @param target
-   */
-  public abstract void showUrl(String url, String target);
-
-  /**
-   * called when the binding thinks the UI needs to be refreshed after a Jmol
+   * called when the binding thinks the UI needs to be refreshed after a Chimera
    * state change. this could be because structures were loaded, or because an
-   * error has occured.
+   * error has occurred.
    */
   public abstract void refreshGUI();
 
@@ -1252,8 +1274,8 @@ public abstract class JalviewChimeraBinding extends
 
   /**
    * 
-   * @return true if Jmol is still restoring state or loading is still going on
-   *         (see setFinsihedLoadingFromArchive)
+   * @return true if Chimeral is still restoring state or loading is still going
+   *         on (see setFinsihedLoadingFromArchive)
    */
   public boolean isLoadingFromArchive()
   {
@@ -1271,13 +1293,22 @@ public abstract class JalviewChimeraBinding extends
     loadingFinished = finishedLoading;
   }
 
-  public void setBackgroundColour(java.awt.Color col)
+  /**
+   * Send the Chimera 'background solid <color>" command.
+   * 
+   * @see https
+   *      ://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/background
+   *      .html
+   * @param col
+   */
+  public void setBackgroundColour(Color col)
   {
     viewerCommandHistory(false);
-    // todo set background colour
-    viewer.sendChimeraCommand(
-            "background [" + col.getRed() + "," + col.getGreen() + ","
-                    + col.getBlue() + "];", false);
+    double normalise = 255D;
+    final String command = "background solid " + col.getRed() / normalise + ","
+            + col.getGreen() / normalise + "," + col.getBlue()
+            / normalise + ";";
+    viewer.sendChimeraCommand(command, false);
     viewerCommandHistory(true);
   }
 
@@ -1289,21 +1320,20 @@ public abstract class JalviewChimeraBinding extends
   public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe,
           SequenceI[][] seq, String[][] chns)
   {
-    int pe = -1;
-    Vector v = new Vector();
-    Vector rtn = new Vector();
+    List<PDBEntry> v = new ArrayList<PDBEntry>();
+    List<int[]> rtn = new ArrayList<int[]>();
     for (int i = 0; i < pdbentry.length; i++)
     {
-      v.addElement(pdbentry[i]);
+      v.add(pdbentry[i]);
     }
     for (int i = 0; i < pdbe.length; i++)
     {
       int r = v.indexOf(pdbe[i]);
       if (r == -1 || r >= pdbentry.length)
       {
-        rtn.addElement(new int[]
+        rtn.add(new int[]
         { v.size(), i });
-        v.addElement(pdbe[i]);
+        v.add(pdbe[i]);
       }
       else
       {
@@ -1311,12 +1341,11 @@ public abstract class JalviewChimeraBinding extends
         addSequenceAndChain(r, seq[i], chns[i]);
       }
     }
-    pdbe = new PDBEntry[v.size()];
-    v.copyInto(pdbe);
+    pdbe = v.toArray(new PDBEntry[v.size()]);
     pdbentry = pdbe;
     if (rtn.size() > 0)
     {
-      // expand the tied seuqence[] and string[] arrays
+      // expand the tied sequence[] and string[] arrays
       SequenceI[][] sqs = new SequenceI[pdbentry.length][];
       String[][] sch = new String[pdbentry.length][];
       System.arraycopy(sequence, 0, sqs, 0, sequence.length);
@@ -1326,7 +1355,7 @@ public abstract class JalviewChimeraBinding extends
       pdbe = new PDBEntry[rtn.size()];
       for (int r = 0; r < pdbe.length; r++)
       {
-        int[] stri = ((int[]) rtn.elementAt(r));
+        int[] stri = (rtn.get(r));
         // record the pdb file as a new addition
         pdbe[r] = pdbentry[stri[0]];
         // and add the new sequence/chain entries
@@ -1340,9 +1369,14 @@ public abstract class JalviewChimeraBinding extends
     return pdbe;
   }
 
+  /**
+   * Adds sequences to the pe'th pdbentry's sequence set.
+   * 
+   * @param pe
+   * @param seq
+   */
   public void addSequence(int pe, SequenceI[] seq)
   {
-    // add sequences to the pe'th pdbentry's seuqence set.
     addSequenceAndChain(pe, seq, null);
   }
 
@@ -1350,11 +1384,14 @@ public abstract class JalviewChimeraBinding extends
   {
     if (pe < 0 || pe >= pdbentry.length)
     {
-      throw new Error(MessageManager.formatMessage("error.implementation_error_no_pdbentry_from_index", new String[]{Integer.valueOf(pe).toString()}));
+      throw new Error(MessageManager.formatMessage(
+              "error.implementation_error_no_pdbentry_from_index",
+              new Object[]
+              { Integer.valueOf(pe).toString() }));
     }
     final String nullChain = "TheNullChain";
-    Vector s = new Vector();
-    Vector c = new Vector();
+    List<SequenceI> s = new ArrayList<SequenceI>();
+    List<String> c = new ArrayList<String>();
     if (chains == null)
     {
       chains = new String[pdbentry.length][];
@@ -1363,23 +1400,23 @@ public abstract class JalviewChimeraBinding extends
     {
       for (int i = 0; i < sequence[pe].length; i++)
       {
-        s.addElement(sequence[pe][i]);
+        s.add(sequence[pe][i]);
         if (chains[pe] != null)
         {
           if (i < chains[pe].length)
           {
-            c.addElement(chains[pe][i]);
+            c.add(chains[pe][i]);
           }
           else
           {
-            c.addElement(nullChain);
+            c.add(nullChain);
           }
         }
         else
         {
           if (tchain != null && tchain.length > 0)
           {
-            c.addElement(nullChain);
+            c.add(nullChain);
           }
         }
       }
@@ -1388,20 +1425,18 @@ public abstract class JalviewChimeraBinding extends
     {
       if (!s.contains(seq[i]))
       {
-        s.addElement(seq[i]);
+        s.add(seq[i]);
         if (tchain != null && i < tchain.length)
         {
-          c.addElement(tchain[i] == null ? nullChain : tchain[i]);
+          c.add(tchain[i] == null ? nullChain : tchain[i]);
         }
       }
     }
-    SequenceI[] tmp = new SequenceI[s.size()];
-    s.copyInto(tmp);
+    SequenceI[] tmp = s.toArray(new SequenceI[s.size()]);
     sequence[pe] = tmp;
     if (c.size() > 0)
     {
-      String[] tch = new String[c.size()];
-      c.copyInto(tch);
+      String[] tch = c.toArray(new String[c.size()]);
       for (int i = 0; i < tch.length; i++)
       {
         if (tch[i] == nullChain)
index 5d4b910..fcb31eb 100644 (file)
@@ -176,14 +176,14 @@ public class AppJmol extends GStructureViewer implements Runnable,
     {
       jmb.setColourBySequence(false);
       seqColour.setSelected(false);
-      jmolColour.setSelected(true);
+      viewerColour.setSelected(true);
     }
     if (usetoColour)
     {
       useAlignmentPanelForColourbyseq(ap);
       jmb.setColourBySequence(true);
       seqColour.setSelected(true);
-      jmolColour.setSelected(false);
+      viewerColour.setSelected(false);
     }
     this.setBounds(bounds);
     initMenus();
@@ -205,7 +205,7 @@ public class AppJmol extends GStructureViewer implements Runnable,
   private void initMenus()
   {
     seqColour.setSelected(jmb.isColourBySequence());
-    jmolColour.setSelected(!jmb.isColourBySequence());
+    viewerColour.setSelected(!jmb.isColourBySequence());
     if (_colourwith == null)
     {
       _colourwith = new Vector<AlignmentPanel>();
@@ -251,8 +251,8 @@ public class AppJmol extends GStructureViewer implements Runnable,
               }
             });
     handler.itemStateChanged(null);
-    jmolActionMenu.add(alpanels);
-    jmolActionMenu.addMenuListener(new MenuListener()
+    viewerActionMenu.add(alpanels);
+    viewerActionMenu.addMenuListener(new MenuListener()
     {
 
       @Override
@@ -303,8 +303,13 @@ public class AppJmol extends GStructureViewer implements Runnable,
                       "label.pdb_entry_is_already_displayed", new String[]
                       { pdbentry.getId() }), MessageManager.formatMessage(
                       "label.map_sequences_to_visible_window", new String[]
-                      { pdbentry.getId() }), JOptionPane.YES_NO_OPTION);
+                      { pdbentry.getId() }),
+              JOptionPane.YES_NO_CANCEL_OPTION);
 
+      if (option == JOptionPane.CANCEL_OPTION)
+      {
+        return;
+      }
       if (option == JOptionPane.YES_OPTION)
       {
         // TODO : Fix multiple seq to one chain issue here.
@@ -366,7 +371,11 @@ public class AppJmol extends GStructureViewer implements Runnable,
                                 { pdbentry.getId(), topJmol.getTitle() }),
                         MessageManager
                                 .getString("label.align_to_existing_structure_view"),
-                        JOptionPane.YES_NO_OPTION);
+                        JOptionPane.YES_NO_CANCEL_OPTION);
+        if (option == JOptionPane.CANCEL_OPTION)
+        {
+          return;
+        }
         if (option == JOptionPane.YES_OPTION)
         {
           topJmol.useAlignmentPanelForSuperposition(ap);
@@ -533,7 +542,7 @@ public class AppJmol extends GStructureViewer implements Runnable,
     useAlignmentPanelForColourbyseq(nap);
     jmb.setColourBySequence(enableColourBySeq);
     seqColour.setSelected(enableColourBySeq);
-    jmolColour.setSelected(!enableColourBySeq);
+    viewerColour.setSelected(!enableColourBySeq);
   }
 
   public void useAlignmentPanelForColourbyseq(AlignmentPanel nap)
@@ -614,25 +623,22 @@ public class AppJmol extends GStructureViewer implements Runnable,
     return;
   }
 
-  private Vector getJmolsFor(AlignmentPanel ap2)
+  private Vector getJmolsFor(AlignmentPanel apanel)
   {
-    Vector otherJmols = new Vector();
-    // Now this AppJmol is mapped to new sequences. We must add them to
-    // the exisiting array
+    Vector result = new Vector();
     JInternalFrame[] frames = Desktop.instance.getAllFrames();
 
-    for (int i = 0; i < frames.length; i++)
+    for (JInternalFrame frame : frames)
     {
-      if (frames[i] instanceof AppJmol)
+      if (frame instanceof AppJmol)
       {
-        AppJmol topJmol = ((AppJmol) frames[i]);
-        if (topJmol.isLinkedWith(ap2))
+        if (((AppJmol) frame).isLinkedWith(apanel))
         {
-          otherJmols.addElement(topJmol);
+          result.addElement(frame);
         }
       }
     }
-    return otherJmols;
+    return result;
   }
 
   void initJmol(String command)
@@ -927,6 +933,7 @@ public class AppJmol extends GStructureViewer implements Runnable,
     worker = null;
   }
 
+  @Override
   public void pdbFile_actionPerformed(ActionEvent actionEvent)
   {
     JalviewFileChooser chooser = new JalviewFileChooser(
@@ -964,6 +971,7 @@ public class AppJmol extends GStructureViewer implements Runnable,
     }
   }
 
+  @Override
   public void viewMapping_actionPerformed(ActionEvent actionEvent)
   {
     jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
@@ -987,23 +995,13 @@ public class AppJmol extends GStructureViewer implements Runnable,
             600);
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
+  @Override
   public void eps_actionPerformed(ActionEvent e)
   {
     makePDBImage(jalview.util.ImageMaker.TYPE.EPS);
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
+  @Override
   public void png_actionPerformed(ActionEvent e)
   {
     makePDBImage(jalview.util.ImageMaker.TYPE.PNG);
@@ -1045,15 +1043,17 @@ public class AppJmol extends GStructureViewer implements Runnable,
     }
   }
 
-  public void jmolColour_actionPerformed(ActionEvent actionEvent)
+  @Override
+  public void viewerColour_actionPerformed(ActionEvent actionEvent)
   {
-    if (jmolColour.isSelected())
+    if (viewerColour.isSelected())
     {
       // disable automatic sequence colouring.
       jmb.setColourBySequence(false);
     }
   }
 
+  @Override
   public void seqColour_actionPerformed(ActionEvent actionEvent)
   {
     jmb.setColourBySequence(seqColour.isSelected());
@@ -1079,71 +1079,83 @@ public class AppJmol extends GStructureViewer implements Runnable,
     }
   }
 
+  @Override
   public void chainColour_actionPerformed(ActionEvent actionEvent)
   {
     chainColour.setSelected(true);
     jmb.colourByChain();
   }
 
+  @Override
   public void chargeColour_actionPerformed(ActionEvent actionEvent)
   {
     chargeColour.setSelected(true);
     jmb.colourByCharge();
   }
 
+  @Override
   public void zappoColour_actionPerformed(ActionEvent actionEvent)
   {
     zappoColour.setSelected(true);
     jmb.setJalviewColourScheme(new ZappoColourScheme());
   }
 
+  @Override
   public void taylorColour_actionPerformed(ActionEvent actionEvent)
   {
     taylorColour.setSelected(true);
     jmb.setJalviewColourScheme(new TaylorColourScheme());
   }
 
+  @Override
   public void hydroColour_actionPerformed(ActionEvent actionEvent)
   {
     hydroColour.setSelected(true);
     jmb.setJalviewColourScheme(new HydrophobicColourScheme());
   }
 
+  @Override
   public void helixColour_actionPerformed(ActionEvent actionEvent)
   {
     helixColour.setSelected(true);
     jmb.setJalviewColourScheme(new HelixColourScheme());
   }
 
+  @Override
   public void strandColour_actionPerformed(ActionEvent actionEvent)
   {
     strandColour.setSelected(true);
     jmb.setJalviewColourScheme(new StrandColourScheme());
   }
 
+  @Override
   public void turnColour_actionPerformed(ActionEvent actionEvent)
   {
     turnColour.setSelected(true);
     jmb.setJalviewColourScheme(new TurnColourScheme());
   }
 
+  @Override
   public void buriedColour_actionPerformed(ActionEvent actionEvent)
   {
     buriedColour.setSelected(true);
     jmb.setJalviewColourScheme(new BuriedColourScheme());
   }
 
+  @Override
   public void purinePyrimidineColour_actionPerformed(ActionEvent actionEvent)
   {
     setJalviewColourScheme(new PurinePyrimidineColourScheme());
   }
 
+  @Override
   public void userColour_actionPerformed(ActionEvent actionEvent)
   {
     userColour.setSelected(true);
     new UserDefinedColours(this, null);
   }
 
+  @Override
   public void backGround_actionPerformed(ActionEvent actionEvent)
   {
     java.awt.Color col = JColorChooser.showDialog(this,
@@ -1154,7 +1166,8 @@ public class AppJmol extends GStructureViewer implements Runnable,
     }
   }
 
-  public void jmolHelp_actionPerformed(ActionEvent actionEvent)
+  @Override
+  public void showHelp_actionPerformed(ActionEvent actionEvent)
   {
     try
     {
@@ -1274,7 +1287,7 @@ public class AppJmol extends GStructureViewer implements Runnable,
     this.setTitle(jmb.getViewerTitle());
     if (jmb.getPdbFile().length > 1 && jmb.sequence.length > 1)
     {
-      jmolActionMenu.setVisible(true);
+      viewerActionMenu.setVisible(true);
     }
     if (!jmb.isLoadingFromArchive())
     {
@@ -1293,11 +1306,11 @@ public class AppJmol extends GStructureViewer implements Runnable,
       _alignwith.add(ap);
     }
     ;
-    for (Component c : jmolActionMenu.getMenuComponents())
+    for (Component c : viewerActionMenu.getMenuComponents())
     {
       if (c != alignStructs)
       {
-        jmolActionMenu.remove((JMenuItem) c);
+        viewerActionMenu.remove((JMenuItem) c);
       }
     }
     final ItemListener handler;
index 236d094..cfac4ef 100644 (file)
@@ -44,6 +44,7 @@ import jalview.schemes.TurnColourScheme;
 import jalview.schemes.ZappoColourScheme;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
+import jalview.ws.dbsources.Pdb;
 
 import java.awt.Component;
 import java.awt.event.ActionEvent;
@@ -54,9 +55,9 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileReader;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.List;
 import java.util.Vector;
 
@@ -81,70 +82,59 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
         ViewSetProvider, JalviewStructureDisplayI
 
 {
-  JalviewChimeraBindingModel jmb;
+  private JalviewChimeraBindingModel jmb;
+
+  /*
+   * list of sequenceSet ids associated with the view
+   */
+  private ArrayList<String> _aps = new ArrayList<String>();
+
+  /*
+   * list of alignment panels to use for superposition
+   */
+  private Vector<AlignmentPanel> _alignwith = new Vector<AlignmentPanel>();
+
+  /*
+   * list of alignment panels that are used for colouring structures by aligned
+   * sequences
+   */
+  private Vector<AlignmentPanel> _colourwith = new Vector<AlignmentPanel>();
+
+  private boolean allChainsSelected = false;
+
+  private boolean alignAddedStructures = false;
 
   AlignmentPanel ap;
 
-  Vector atomsPicked = new Vector();
+  /*
+   * state flag for PDB retrieval thread
+   */
+  private boolean _started = false;
 
   private boolean addingStructures = false;
 
-  ViewSelectionMenu seqColourBy;
+  private IProgressIndicator progressBar = null;
+
+  private String viewId = null;
+
+  /*
+   * pdb retrieval thread.
+   */
+  private Thread worker = null;
 
   /**
-   * 
-   * @param files
-   * @param ids
-   * @param seqs
-   * @param ap
-   * @param usetoColour
-   *          - add the alignment panel to the list used for colouring these
-   *          structures
-   * @param useToAlign
-   *          - add the alignment panel to the list used for aligning these
-   *          structures
-   * @param leaveColouringToJmol
-   *          - do not update the colours from any other source. Jmol is
-   *          handling them
-   * @param loadStatus
-   * @param bounds
-   * @param viewid
-   * 
-   *          public ChimeraViewFrame(String[] files, String[] ids,
-   *          SequenceI[][] seqs, AlignmentPanel ap, boolean usetoColour,
-   *          boolean useToAlign, boolean leaveColouringToJmol, String
-   *          loadStatus, Rectangle bounds, String viewid) { 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]); pdbentrys[i] =
-   *          pdbentry; } // / TODO: check if protocol is needed to be set, and
-   *          if chains are // autodiscovered. jmb = new
-   *          JalviewChimeraBindingModel(this,
-   *          ap.getStructureSelectionManager(), pdbentrys, seqs, null, null);
-   * 
-   *          jmb.setLoadingFromArchive(true); addAlignmentPanel(ap); if
-   *          (useToAlign) { useAlignmentPanelForSuperposition(ap); } if
-   *          (leaveColouringToJmol || !usetoColour) {
-   *          jmb.setColourBySequence(false); seqColour.setSelected(false);
-   *          jmolColour.setSelected(true); } if (usetoColour) {
-   *          useAlignmentPanelForColourbyseq(ap);
-   *          jmb.setColourBySequence(true); seqColour.setSelected(true);
-   *          jmolColour.setSelected(false); } this.setBounds(bounds);
-   *          initMenus(); viewId = viewid; //
-   *          jalview.gui.Desktop.addInternalFrame(this, "Loading File", //
-   *          bounds.width,bounds.height);
-   * 
-   *          this.addInternalFrameListener(new InternalFrameAdapter() { public
-   *          void internalFrameClosing(InternalFrameEvent internalFrameEvent) {
-   *          closeViewer(); } }); initJmol(loadStatus); // pdbentry, seq,
-   *          JBPCHECK!
-   * 
-   *          }
+   * Initialise menu options.
    */
   private void 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"));
     seqColour.setSelected(jmb.isColourBySequence());
-    jmolColour.setSelected(!jmb.isColourBySequence());
+    viewerColour.setSelected(!jmb.isColourBySequence());
     if (_colourwith == null)
     {
       _colourwith = new Vector<AlignmentPanel>();
@@ -154,10 +144,16 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
       _alignwith = new Vector<AlignmentPanel>();
     }
 
-    seqColourBy = new ViewSelectionMenu(MessageManager.getString("label.colour_by"), this, _colourwith,
+    // no colour by chain command in Chimera?
+    chainColour.setVisible(false);
+
+    // save As not yet implemented
+    savemenu.setVisible(false);
+
+    ViewSelectionMenu seqColourBy = new ViewSelectionMenu(
+            MessageManager.getString("label.colour_by"), this, _colourwith,
             new ItemListener()
             {
-
               @Override
               public void itemStateChanged(ItemEvent e)
               {
@@ -167,17 +163,17 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
                 }
                 else
                 {
-                  // update the jmol display now.
+                  // update the Chimera display now.
                   seqColour_actionPerformed(null);
                 }
               }
             });
     viewMenu.add(seqColourBy);
     final ItemListener handler;
-    JMenu alpanels = new ViewSelectionMenu(MessageManager.getString("label.superpose_with"), this,
+    JMenu alpanels = new ViewSelectionMenu(
+            MessageManager.getString("label.superpose_with"), this,
             _alignwith, handler = new ItemListener()
             {
-
               @Override
               public void itemStateChanged(ItemEvent e)
               {
@@ -185,13 +181,13 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
                 alignStructs.setToolTipText(MessageManager
                         .formatMessage(
                                 "label.align_structures_using_linked_alignment_views",
-                                new String[]
+                                new Object[]
                                 { new Integer(_alignwith.size()).toString() }));
               }
             });
     handler.itemStateChanged(null);
-    jmolActionMenu.add(alpanels);
-    jmolActionMenu.addMenuListener(new MenuListener()
+    viewerActionMenu.add(alpanels);
+    viewerActionMenu.addMenuListener(new MenuListener()
     {
 
       @Override
@@ -204,22 +200,18 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
       public void menuDeselected(MenuEvent e)
       {
         // TODO Auto-generated method stub
-
       }
 
       @Override
       public void menuCanceled(MenuEvent e)
       {
         // TODO Auto-generated method stub
-
       }
     });
   }
 
-  IProgressIndicator progressBar = null;
-
   /**
-   * add a single PDB structure to a new or existing Jmol view
+   * add a single PDB structure to a new or existing Chimera view
    * 
    * @param pdbentry
    * @param seq
@@ -229,6 +221,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
   public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq,
           String[] chains, final AlignmentPanel ap)
   {
+    super();
     progressBar = ap.alignFrame;
     // ////////////////////////////////
     // Is the pdb file already loaded?
@@ -239,11 +232,16 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     {
       int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
               MessageManager.formatMessage(
-                      "label.pdb_entry_is_already_displayed", new String[]
+                      "label.pdb_entry_is_already_displayed", new Object[]
                       { pdbentry.getId() }), MessageManager.formatMessage(
-                      "label.map_sequences_to_visible_window", new String[]
-                      { pdbentry.getId() }), JOptionPane.YES_NO_OPTION);
+                      "label.map_sequences_to_visible_window", new Object[]
+                      { pdbentry.getId() }),
+              JOptionPane.YES_NO_CANCEL_OPTION);
 
+      if (option == JOptionPane.CANCEL_OPTION)
+      {
+        return;
+      }
       if (option == JOptionPane.YES_OPTION)
       {
         // TODO : Fix multiple seq to one chain issue here.
@@ -255,26 +253,26 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
           ap.paintAlignment(true);
         }
 
-        // Now this AppJmol is mapped to new sequences. We must add them to
-        // the exisiting array
+        // Now this ChimeraViewFrame is mapped to new sequences. We must add
+        // them to the existing array
         JInternalFrame[] frames = Desktop.instance.getAllFrames();
 
-        for (int i = 0; i < frames.length; i++)
+        for (JInternalFrame frame : frames)
         {
-          if (frames[i] instanceof ChimeraViewFrame)
+          if (frame instanceof ChimeraViewFrame)
           {
-            final ChimeraViewFrame topJmol = ((ChimeraViewFrame) frames[i]);
+            final ChimeraViewFrame topView = ((ChimeraViewFrame) frame);
             // JBPNOTE: this looks like a binding routine, rather than a gui
             // routine
-            for (int pe = 0; pe < topJmol.jmb.pdbentry.length; pe++)
+            for (int pe = 0; pe < topView.jmb.pdbentry.length; pe++)
             {
-              if (topJmol.jmb.pdbentry[pe].getFile().equals(alreadyMapped))
+              if (topView.jmb.pdbentry[pe].getFile().equals(alreadyMapped))
               {
-                topJmol.jmb.addSequence(pe, seq);
-                topJmol.addAlignmentPanel(ap);
+                topView.jmb.addSequence(pe, seq);
+                topView.addAlignmentPanel(ap);
                 // add it to the set used for colouring
-                topJmol.useAlignmentPanelForColourbyseq(ap);
-                topJmol.buildChimeraActionMenu();
+                topView.useAlignmentPanelForColourbyseq(ap);
+                topView.buildChimeraActionMenu();
                 ap.getStructureSelectionManager()
                         .sequenceColoursChanged(ap);
                 break;
@@ -287,40 +285,37 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
       }
     }
     // /////////////////////////////////
-    // Check if there are other Jmol views involving this alignment
+    // Check if there are other Chimera views involving this alignment
     // and prompt user about adding this molecule to one of them
-    Vector existingViews = getJmolsFor(ap);
-    if (existingViews.size() > 0)
+    List<ChimeraViewFrame> existingViews = getChimeraWindowsFor(ap);
+    for (ChimeraViewFrame topView : existingViews)
     {
-      Enumeration jm = existingViews.elements();
-      while (jm.hasMoreElements())
+      // TODO: highlight topView in view somehow
+      int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
+              MessageManager.formatMessage("label.add_pdbentry_to_view",
+                      new Object[]
+                      { pdbentry.getId(), topView.getTitle() }),
+              MessageManager
+                      .getString("label.align_to_existing_structure_view"),
+              JOptionPane.YES_NO_CANCEL_OPTION);
+      if (option == JOptionPane.CANCEL_OPTION)
       {
-        ChimeraViewFrame topJmol = (ChimeraViewFrame) jm.nextElement();
-        // TODO: highlight topJmol in view somehow
-        int option = JOptionPane
-                .showInternalConfirmDialog(
-                        Desktop.desktop,
-                        MessageManager.formatMessage(
-                                "label.add_pdbentry_to_view", new String[]
-                                { pdbentry.getId(), topJmol.getTitle() }),
-                        MessageManager
-                                .getString("label.align_to_existing_structure_view"),
-                        JOptionPane.YES_NO_OPTION);
-        if (option == JOptionPane.YES_OPTION)
-        {
-          topJmol.useAlignmentPanelForSuperposition(ap);
-          topJmol.addStructure(pdbentry, seq, chains, true, ap.alignFrame);
-          return;
-        }
+        return;
+      }
+      if (option == JOptionPane.YES_OPTION)
+      {
+        topView.useAlignmentPanelForSuperposition(ap);
+        topView.addStructure(pdbentry, seq, chains, true, ap.alignFrame);
+        return;
       }
     }
     // /////////////////////////////////
-    openNewJmol(ap, new PDBEntry[]
+    openNewChimera(ap, new PDBEntry[]
     { pdbentry }, new SequenceI[][]
     { seq });
   }
 
-  private void openNewJmol(AlignmentPanel ap, PDBEntry[] pdbentrys,
+  private void openNewChimera(AlignmentPanel ap, PDBEntry[] pdbentrys,
           SequenceI[][] seqs)
   {
     progressBar = ap.alignFrame;
@@ -353,7 +348,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
   }
 
   /**
-   * create a new Jmol containing several structures superimposed using the
+   * create a new viewer containing several structures superimposed using the
    * given alignPanel.
    * 
    * @param ap
@@ -363,14 +358,10 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
   public ChimeraViewFrame(AlignmentPanel ap, PDBEntry[] pe,
           SequenceI[][] seqs)
   {
-    openNewJmol(ap, pe, seqs);
+    super();
+    openNewChimera(ap, pe, seqs);
   }
 
-  /**
-   * list of sequenceSet ids associated with the view
-   */
-  ArrayList<String> _aps = new ArrayList();
-
   public AlignmentPanel[] getAllAlignmentPanels()
   {
     AlignmentPanel[] t, list = new AlignmentPanel[0];
@@ -390,17 +381,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
   }
 
   /**
-   * list of alignment panels to use for superposition
-   */
-  Vector<AlignmentPanel> _alignwith = new Vector<AlignmentPanel>();
-
-  /**
-   * list of alignment panels that are used for colouring structures by aligned
-   * sequences
-   */
-  Vector<AlignmentPanel> _colourwith = new Vector<AlignmentPanel>();
-
-  /**
    * set the primary alignmentPanel reference and add another alignPanel to the
    * list of ones to use for colouring and aligning
    * 
@@ -473,7 +453,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     useAlignmentPanelForColourbyseq(nap);
     jmb.setColourBySequence(enableColourBySeq);
     seqColour.setSelected(enableColourBySeq);
-    jmolColour.setSelected(!enableColourBySeq);
+    viewerColour.setSelected(!enableColourBySeq);
   }
 
   public void useAlignmentPanelForColourbyseq(AlignmentPanel nap)
@@ -494,11 +474,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
   }
 
   /**
-   * pdb retrieval thread.
-   */
-  private Thread worker = null;
-
-  /**
    * add a new structure (with associated sequences and chains) to this viewer,
    * retrieving it if necessary first.
    * 
@@ -554,25 +529,22 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     return;
   }
 
-  private Vector getJmolsFor(AlignmentPanel ap2)
+  private List<ChimeraViewFrame> getChimeraWindowsFor(AlignmentPanel apanel)
   {
-    Vector otherJmols = new Vector();
-    // Now this AppJmol is mapped to new sequences. We must add them to
-    // the exisiting array
+    List<ChimeraViewFrame> result = new ArrayList<ChimeraViewFrame>();
     JInternalFrame[] frames = Desktop.instance.getAllFrames();
 
-    for (int i = 0; i < frames.length; i++)
+    for (JInternalFrame frame : frames)
     {
-      if (frames[i] instanceof ChimeraViewFrame)
+      if (frame instanceof ChimeraViewFrame)
       {
-        ChimeraViewFrame topJmol = ((ChimeraViewFrame) frames[i]);
-        if (topJmol.isLinkedWith(ap2))
+        if (((ChimeraViewFrame) frame).isLinkedWith(apanel))
         {
-          otherJmols.addElement(topJmol);
+          result.add((ChimeraViewFrame) frame);
         }
       }
     }
-    return otherJmols;
+    return result;
   }
 
   void initChimera(String command)
@@ -580,7 +552,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     jmb.setFinishedInit(false);
     // TODO: consider waiting until the structure/view is fully loaded before
     // displaying
-    jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle(),
+    jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle(true),
             getBounds().width, getBounds().height);
     if (command == null)
     {
@@ -590,10 +562,10 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     jmb.setFinishedInit(true);
   }
 
-  void setChainMenuItems(Vector chains)
+  void setChainMenuItems(List<String> chainNames)
   {
     chainMenu.removeAll();
-    if (chains == null)
+    if (chainNames == null)
     {
       return;
     }
@@ -607,7 +579,9 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
         for (int i = 0; i < chainMenu.getItemCount(); i++)
         {
           if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
+          {
             ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
+          }
         }
         centerViewer();
         allChainsSelected = false;
@@ -616,15 +590,17 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
 
     chainMenu.add(menuItem);
 
-    for (int c = 0; c < chains.size(); c++)
+    for (String chainName : chainNames)
     {
-      menuItem = new JCheckBoxMenuItem(chains.elementAt(c).toString(), true);
+      menuItem = new JCheckBoxMenuItem(chainName, true);
       menuItem.addItemListener(new ItemListener()
       {
         public void itemStateChanged(ItemEvent evt)
         {
           if (!allChainsSelected)
+          {
             centerViewer();
+          }
         }
       });
 
@@ -632,15 +608,9 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     }
   }
 
-  boolean allChainsSelected = false;
-
-  private boolean alignAddedStructures = false;
-
   void centerViewer()
   {
-    Vector toshow = new Vector();
-    String lbl;
-    int mlength, p, mnum;
+    List<String> toshow = new ArrayList<String>();
     for (int i = 0; i < chainMenu.getItemCount(); i++)
     {
       if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
@@ -648,16 +618,31 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
         JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
         if (item.isSelected())
         {
-          toshow.addElement(item.getText());
+          toshow.add(item.getText());
         }
       }
     }
     jmb.centerViewer(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.
+   */
   public void closeViewer()
   {
-    jmb.closeViewer();
+    if (jmb.isChimeraRunning())
+    {
+      String prompt = MessageManager
+              .formatMessage("label.confirm_close_chimera", new Object[]
+              { jmb.getViewerTitle(false) });
+      prompt = JvSwingUtils.wrapTooltip(true, prompt);
+      int confirm = JOptionPane.showConfirmDialog(this, prompt,
+              MessageManager.getString("label.close_viewer"),
+              JOptionPane.YES_NO_OPTION);
+      jmb.closeViewer(confirm == JOptionPane.YES_OPTION);
+    }
     ap = null;
     _aps.clear();
     _alignwith.clear();
@@ -668,73 +653,45 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
   }
 
   /**
-   * state flag for PDB retrieval thread
+   * Open any newly added PDB structures in Chimera, having first fetched data
+   * from PDB (if not already saved).
    */
-  private boolean _started = false;
-
   public void run()
   {
     _started = true;
-    String pdbid = "";
-    // todo - record which pdbids were successfuly imported.
-    StringBuffer errormsgs = new StringBuffer(), files = new StringBuffer();
-    List<String> fileToLoad=new ArrayList<String>();
+    // 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<Integer> filePDBpos = new ArrayList<Integer>();
+    PDBEntry thePdbEntry = null;
     try
     {
       String[] curfiles = jmb.getPdbFile(); // files currently in viewer
       // TODO: replace with reference fetching/transfer code (validate PDBentry
       // as a DBRef?)
-      jalview.ws.dbsources.Pdb pdbclient = new jalview.ws.dbsources.Pdb();
       for (int pi = 0; pi < jmb.pdbentry.length; pi++)
       {
         String file = null;
-        if (jmb.pdbentry[pi].getFile()==null) 
+        thePdbEntry = jmb.pdbentry[pi];
+        if (thePdbEntry.getFile() == null)
         {
-          // retrieve the pdb and store it locally
-          AlignmentI pdbseq = null;
-          pdbid = jmb.pdbentry[pi].getId();
-          long hdl = pdbid.hashCode() - System.currentTimeMillis();
-          if (progressBar != null)
+          /*
+           * Retrieve PDB data, save to file, attach to PDBEntry
+           */
+          file = fetchPdbFile(thePdbEntry);
+          if (file == null)
           {
-            progressBar.setProgressBar(MessageManager.formatMessage("status.fetching_pdb", new String[]{pdbid}), hdl);
-          }
-          try
-          {
-            pdbseq = pdbclient.getSequenceRecords(pdbid = jmb.pdbentry[pi]
-                    .getId());
-          } catch (OutOfMemoryError oomerror)
-          {
-            new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
-          } catch (Exception ex)
-          {
-            ex.printStackTrace();
-            errormsgs.append("'" + pdbid + "'");
-          }
-          if (progressBar != null)
-          {
-            progressBar.setProgressBar(MessageManager.getString("label.state_completed"), hdl);
-          }
-          if (pdbseq != null)
-          {
-            // just transfer the file name from the first sequence's first
-            // PDBEntry
-            file = new File(((PDBEntry) pdbseq.getSequenceAt(0).getPDBId()
-                    .elementAt(0)).getFile()).getAbsolutePath();
-            jmb.pdbentry[pi].setFile(file);
-
-            files.append(" \"" + Platform.escapeString(file) + "\"");
-          }
-          else
-          {
-            errormsgs.append("'" + pdbid + "' ");
+            errormsgs.append("'" + thePdbEntry.getId() + "' ");
           }
         }
         else
         {
-          file = new File(jmb.pdbentry[pi].getFile())
-          .getAbsoluteFile().getPath();
+          /*
+           * Got file already - ignore if already loaded in Chimera.
+           */
+          file = new File(thePdbEntry.getFile()).getAbsoluteFile()
+                  .getPath();
           if (curfiles != null && curfiles.length > 0)
           {
             addingStructures = true; // already files loaded.
@@ -747,37 +704,35 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
               }
             }
           }
-          
-          if (file != null)
-          {
-            fileToLoad.add(file);
-            filePDB.add(jmb.pdbentry[pi]);
-            filePDBpos.add(Integer.valueOf(pi));
-            files.append(" \"" + Platform.escapeString(file) + "\"");
-          }
+        }
+        if (file != null)
+        {
+          filePDB.add(thePdbEntry);
+          filePDBpos.add(Integer.valueOf(pi));
+          files.append(" \"" + Platform.escapeString(file) + "\"");
         }
       }
     } catch (OutOfMemoryError oomerror)
     {
-      new OOMWarning("Retrieving PDB files: " + pdbid, oomerror);
+      new OOMWarning("Retrieving PDB files: " + thePdbEntry.getId(),
+              oomerror);
     } catch (Exception ex)
     {
       ex.printStackTrace();
-      errormsgs.append("When retrieving pdbfiles : current was: '" + pdbid
-              + "'");
+      errormsgs.append("When retrieving pdbfiles for '"
+              + thePdbEntry.getId() + "'");
     }
     if (errormsgs.length() > 0)
     {
 
       JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
               .formatMessage("label.pdb_entries_couldnt_be_retrieved",
-                      new String[]
+                      new Object[]
                       { errormsgs.toString() }), MessageManager
               .getString("label.couldnt_load_file"),
               JOptionPane.ERROR_MESSAGE);
-
     }
-    long lastnotify = jmb.getLoadNotifiesHandled();
+
     if (files.length() > 0)
     {
       if (!addingStructures)
@@ -789,8 +744,8 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
         {
           Cache.log.error("Couldn't open Chimera viewer!", ex);
         }
-      } 
-      int num=-1;
+      }
+      int num = -1;
       for (PDBEntry pe : filePDB)
       {
         num++;
@@ -798,26 +753,24 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
         {
           try
           {
-            int pos=filePDBpos.get(num).intValue();
+            int pos = filePDBpos.get(num).intValue();
             jmb.openFile(pe);
             jmb.addSequence(pos, jmb.sequence[pos]);
-            File fl=new File(pe.getFile());
+            File fl = new File(pe.getFile());
             String protocol = AppletFormatAdapter.URL;
             try
             {
               if (fl.exists())
-                {
-                  protocol = AppletFormatAdapter.FILE;
-                }
-              } catch (Exception e)
-              {
-              } catch (Error e)
               {
+                protocol = AppletFormatAdapter.FILE;
               }
-              // Explicitly map to the filename used by Jmol ;
-              jmb.ssm.setMapping(jmb.sequence[pos], null, pe.getFile(),
-                      protocol);
-              // pdbentry[pe].getFile(), protocol);
+            } catch (Throwable e)
+            {
+            }
+            // Explicitly map to the filename used by Chimera ;
+            // TODO: use pe.getId() instead of pe.getFile() ?
+            jmb.ssm.setMapping(jmb.sequence[pos], null, pe.getFile(),
+                    protocol);
           } catch (OutOfMemoryError oomerror)
           {
             new OOMWarning(
@@ -833,10 +786,9 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
           }
         }
       }
-      // jmb.getPdbFile();
       jmb.setFinishedInit(true);
       jmb.setLoadingFromArchive(false);
-      
+
       // refresh the sequence colours for the new structure(s)
       for (AlignmentPanel ap : _colourwith)
       {
@@ -860,6 +812,56 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     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 String fetchPdbFile(PDBEntry processingEntry) throws Exception
+  {
+    String filePath = null;
+    Pdb pdbclient = new Pdb();
+    AlignmentI pdbseq = null;
+    String pdbid = processingEntry.getId();
+    long hdl = pdbid.hashCode() - System.currentTimeMillis();
+    if (progressBar != null)
+    {
+      progressBar.setProgressBar(MessageManager.formatMessage(
+              "status.fetching_pdb", new Object[]
+              { pdbid }), hdl);
+    }
+    try
+    {
+      pdbseq = pdbclient.getSequenceRecords(pdbid);
+    } catch (OutOfMemoryError oomerror)
+    {
+      new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
+    } finally
+    {
+      if (progressBar != null)
+      {
+        progressBar.setProgressBar(
+                MessageManager.getString("label.state_completed"), 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(((PDBEntry) pdbseq.getSequenceAt(0).getPDBId()
+              .elementAt(0)).getFile()).getAbsolutePath();
+      processingEntry.setFile(filePath);
+    }
+    return filePath;
+  }
+
+  @Override
   public void pdbFile_actionPerformed(ActionEvent actionEvent)
   {
     JalviewFileChooser chooser = new JalviewFileChooser(
@@ -873,11 +875,11 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
 
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
+      BufferedReader in = null;
       try
       {
         // TODO: cope with multiple PDB files in view
-        BufferedReader in = new BufferedReader(new FileReader(
-                jmb.getPdbFile()[0]));
+        in = new BufferedReader(new FileReader(jmb.getPdbFile()[0]));
         File outFile = chooser.getSelectedFile();
 
         PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
@@ -893,10 +895,23 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
       } catch (Exception ex)
       {
         ex.printStackTrace();
+      } finally
+      {
+        if (in != null)
+        {
+          try
+          {
+            in.close();
+          } catch (IOException e)
+          {
+            e.printStackTrace();
+          }
+        }
       }
     }
   }
 
+  @Override
   public void viewMapping_actionPerformed(ActionEvent actionEvent)
   {
     jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
@@ -920,37 +935,33 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
             600);
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
+  @Override
   public void eps_actionPerformed(ActionEvent e)
   {
-    throw new Error(MessageManager.getString("error.eps_generation_not_implemented"));
+    throw new Error(
+            MessageManager
+                    .getString("error.eps_generation_not_implemented"));
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
+  @Override
   public void png_actionPerformed(ActionEvent e)
   {
-           throw new Error(MessageManager.getString("error.png_generation_not_implemented"));
+    throw new Error(
+            MessageManager
+                    .getString("error.png_generation_not_implemented"));
   }
 
-  public void jmolColour_actionPerformed(ActionEvent actionEvent)
+  @Override
+  public void viewerColour_actionPerformed(ActionEvent actionEvent)
   {
-    if (jmolColour.isSelected())
+    if (viewerColour.isSelected())
     {
       // disable automatic sequence colouring.
       jmb.setColourBySequence(false);
     }
   }
 
+  @Override
   public void seqColour_actionPerformed(ActionEvent actionEvent)
   {
     jmb.setColourBySequence(seqColour.isSelected());
@@ -976,82 +987,96 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     }
   }
 
+  @Override
   public void chainColour_actionPerformed(ActionEvent actionEvent)
   {
     chainColour.setSelected(true);
     jmb.colourByChain();
   }
 
+  @Override
   public void chargeColour_actionPerformed(ActionEvent actionEvent)
   {
     chargeColour.setSelected(true);
     jmb.colourByCharge();
   }
 
+  @Override
   public void zappoColour_actionPerformed(ActionEvent actionEvent)
   {
     zappoColour.setSelected(true);
     jmb.setJalviewColourScheme(new ZappoColourScheme());
   }
 
+  @Override
   public void taylorColour_actionPerformed(ActionEvent actionEvent)
   {
     taylorColour.setSelected(true);
     jmb.setJalviewColourScheme(new TaylorColourScheme());
   }
 
+  @Override
   public void hydroColour_actionPerformed(ActionEvent actionEvent)
   {
     hydroColour.setSelected(true);
     jmb.setJalviewColourScheme(new HydrophobicColourScheme());
   }
 
+  @Override
   public void helixColour_actionPerformed(ActionEvent actionEvent)
   {
     helixColour.setSelected(true);
     jmb.setJalviewColourScheme(new HelixColourScheme());
   }
 
+  @Override
   public void strandColour_actionPerformed(ActionEvent actionEvent)
   {
     strandColour.setSelected(true);
     jmb.setJalviewColourScheme(new StrandColourScheme());
   }
 
+  @Override
   public void turnColour_actionPerformed(ActionEvent actionEvent)
   {
     turnColour.setSelected(true);
     jmb.setJalviewColourScheme(new TurnColourScheme());
   }
 
+  @Override
   public void buriedColour_actionPerformed(ActionEvent actionEvent)
   {
     buriedColour.setSelected(true);
     jmb.setJalviewColourScheme(new BuriedColourScheme());
   }
 
+  @Override
   public void purinePyrimidineColour_actionPerformed(ActionEvent actionEvent)
   {
     setJalviewColourScheme(new PurinePyrimidineColourScheme());
   }
 
+  @Override
   public void userColour_actionPerformed(ActionEvent actionEvent)
   {
     userColour.setSelected(true);
     new UserDefinedColours(this, null);
   }
 
+  @Override
   public void backGround_actionPerformed(ActionEvent actionEvent)
   {
-    java.awt.Color col = JColorChooser.showDialog(this,
-               MessageManager.getString("label.select_backgroud_colour"), null);
+    java.awt.Color col = JColorChooser
+            .showDialog(this, MessageManager
+                    .getString("label.select_backgroud_colour"), null);
     if (col != null)
     {
       jmb.setBackgroundColour(col);
     }
   }
 
-  public void jmolHelp_actionPerformed(ActionEvent actionEvent)
+  @Override
+  public void showHelp_actionPerformed(ActionEvent actionEvent)
   {
     try
     {
@@ -1062,8 +1087,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     }
   }
 
-  String viewId = null;
-
   public String getViewId()
   {
     if (viewId == null)
@@ -1082,10 +1105,10 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
     }
     setChainMenuItems(jmb.chainNames);
 
-    this.setTitle(jmb.getViewerTitle());
+    this.setTitle(jmb.getViewerTitle(true));
     if (jmb.getPdbFile().length > 1 && jmb.sequence.length > 1)
     {
-      jmolActionMenu.setVisible(true);
+      viewerActionMenu.setVisible(true);
     }
     if (!jmb.isLoadingFromArchive())
     {
@@ -1104,14 +1127,13 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
       _alignwith.add(ap);
     }
     ;
-    for (Component c : jmolActionMenu.getMenuComponents())
+    for (Component c : viewerActionMenu.getMenuComponents())
     {
       if (c != alignStructs)
       {
-        jmolActionMenu.remove((JMenuItem) c);
+        viewerActionMenu.remove((JMenuItem) c);
       }
     }
-    final ItemListener handler;
   }
 
   /*
@@ -1194,7 +1216,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
   /**
    * 
    * @param ap2
-   * @return true if this Jmol instance is linked with the given alignPanel
+   * @return true if this Chimera instance is linked with the given alignPanel
    */
   public boolean isLinkedWith(AlignmentPanel ap2)
   {
@@ -1216,7 +1238,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
    * 
    * @return TRUE if the view is NOT being coloured by sequence associations.
    */
-  public boolean isColouredByJmol()
+  public boolean isColouredByChimera()
   {
     return !jmb.isColourBySequence();
   }
index f7c4878..f68b585 100644 (file)
@@ -66,7 +66,9 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
     AlignmentPanel ap = (AlignmentPanel) source, topap;
     // ignore events from panels not used to colour this view
     if (!cvf.isUsedforcolourby(ap))
+    {
       return;
+    }
     if (!isLoadingFromArchive())
     {
       colourBySequence(ap.av.getShowSequenceFeatures(), ap);
@@ -92,11 +94,4 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
     // TODO Auto-generated method stub
 
   }
-
-  @Override
-  public void showUrl(String url, String target)
-  {
-    // TODO Auto-generated method stub
-
-  }
 }
index 2e8aa89..ab4f94f 100755 (executable)
@@ -35,7 +35,9 @@ import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
+import java.io.File;
 import java.util.Collection;
 import java.util.StringTokenizer;
 import java.util.Vector;
@@ -65,6 +67,8 @@ public class Preferences extends GPreferences
 
   public static final String STRUCTURE_DISPLAY = "STRUCTURE_DISPLAY";
 
+  public static final String CHIMERA_PATH = "CHIMERA_PATH";
+
   public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
 
   public static final String SHOW_AUTOCALC_ABOVE = "SHOW_AUTOCALC_ABOVE";
@@ -281,6 +285,25 @@ public class Preferences extends GPreferences
     addTempFactor.setEnabled(structSelected);
     structViewer.setSelectedItem(Cache.getDefault(STRUCTURE_DISPLAY,
             Viewer.JMOL.name()));
+    chimeraPath.setText(Cache.getDefault(CHIMERA_PATH, ""));
+    chimeraPath.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        if (chimeraPath.getText().trim().length() > 0)
+        {
+          File f = new File(chimeraPath.getText());
+          if (!f.canExecute())
+          {
+            JOptionPane.showInternalMessageDialog(Desktop.desktop,
+                    MessageManager.getString("label.invalid_path"),
+                    MessageManager.getString("label.invalid_name"),
+                    JOptionPane.ERROR_MESSAGE);
+          }
+        }
+      }
+    });
 
     /*
      * Set Connections tab defaults
@@ -449,6 +472,7 @@ public class Preferences extends GPreferences
             Boolean.toString(structFromPdb.isSelected()));
     Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY, structViewer
             .getSelectedItem().toString());
+    Cache.setOrRemove(CHIMERA_PATH, chimeraPath.getText());
 
     /*
      * Save Output settings
@@ -466,15 +490,7 @@ public class Preferences extends GPreferences
     /*
      * Save Connections settings
      */
-    if (defaultBrowser.getText().trim().length() < 1)
-    {
-      Cache.applicationProperties.remove("DEFAULT_BROWSER");
-    }
-    else
-    {
-      Cache.applicationProperties.setProperty("DEFAULT_BROWSER",
-              defaultBrowser.getText());
-    }
+    Cache.setOrRemove("DEFAULT_BROWSER", defaultBrowser.getText());
 
     jalview.util.BrowserLauncher.resetBrowser();
 
@@ -502,25 +518,9 @@ public class Preferences extends GPreferences
     Cache.applicationProperties.setProperty("USE_PROXY",
             Boolean.toString(useProxy.isSelected()));
 
-    if (proxyServerTB.getText().trim().length() < 1)
-    {
-      Cache.applicationProperties.remove("PROXY_SERVER");
-    }
-    else
-    {
-      Cache.applicationProperties.setProperty("PROXY_SERVER",
-              proxyServerTB.getText());
-    }
+    Cache.setOrRemove("PROXY_SERVER", proxyServerTB.getText());
 
-    if (proxyPortTB.getText().trim().length() < 1)
-    {
-      Cache.applicationProperties.remove("PROXY_PORT");
-    }
-    else
-    {
-      Cache.applicationProperties.setProperty("PROXY_PORT",
-              proxyPortTB.getText());
-    }
+    Cache.setOrRemove("PROXY_PORT", proxyPortTB.getText());
 
     if (useProxy.isSelected())
     {
index ad7b675..22f12ea 100644 (file)
@@ -115,25 +115,24 @@ public class StructureViewer
     return viewStructures(getViewerType(), ap, pdb, sequenceIs);
   }
 
-  public JalviewStructureDisplayI createView(Viewer jmol, String[] pdbf,
+  public JalviewStructureDisplayI createView(Viewer viewer, String[] pdbf,
           String[] id, SequenceI[][] sq, AlignmentPanel alignPanel,
           boolean useinJmolsuperpos, boolean usetoColourbyseq,
           boolean jmolColouring, String fileloc, Rectangle rect, String vid)
   {
     JalviewStructureDisplayI sview = null;
-    switch (getViewerType())
+    switch (viewer)
     {
     case JMOL:
-
       sview = new AppJmol(pdbf, id, sq, alignPanel, useinJmolsuperpos,
               usetoColourbyseq, jmolColouring, fileloc, rect, vid);
-
       break;
     case CHIMERA:
+      Cache.log.error("Unsupported structure viewer type "
+              + viewer.toString());
       break;
     default:
-      Cache.log.error("Unknown structure viewer type "
-              + getViewerType().toString());
+      Cache.log.error("Unknown structure viewer type " + viewer.toString());
     }
     return sview;
   }
index cd3064e..a232377 100755 (executable)
@@ -140,6 +140,8 @@ public class GPreferences extends JPanel
 
   protected JComboBox<String> structViewer = new JComboBox<String>();
 
+  protected JTextField chimeraPath = new JTextField();
+
   /*
    * Colours tab components
    */
@@ -744,11 +746,26 @@ public class GPreferences extends JPanel
     structureTab.add(viewerLabel);
 
     structViewer.setFont(verdana11);
-    structViewer.setBounds(new Rectangle(150, ypos, 120, height));
+    structViewer.setBounds(new Rectangle(160, ypos, 120, height));
     structViewer.addItem(Viewer.JMOL.name());
     structViewer.addItem(Viewer.CHIMERA.name());
     structureTab.add(structViewer);
 
+    ypos += lineSpacing;
+    JLabel pathLabel = new JLabel();
+    pathLabel.setFont(new java.awt.Font("SansSerif", 0, 11));
+    pathLabel.setHorizontalAlignment(SwingConstants.LEFT);
+    pathLabel.setText(MessageManager.getString("label.chimera_path"));
+    pathLabel.setToolTipText(MessageManager
+            .getString("label.chimera_path_tip"));
+    pathLabel.setBounds(new Rectangle(10, ypos, 140, height));
+    structureTab.add(pathLabel);
+
+    chimeraPath.setFont(verdana11);
+    chimeraPath.setText("");
+    chimeraPath.setBounds(new Rectangle(160, ypos, 300, height));
+    structureTab.add(chimeraPath);
+
     return structureTab;
   }
 
index f6c4e05..58b2eb1 100644 (file)
@@ -22,9 +22,15 @@ package jalview.jbgui;
 
 import jalview.util.MessageManager;
 
-import javax.swing.*;
-import java.awt.event.ActionListener;
 import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JInternalFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JRadioButtonMenuItem;
 
 public class GStructureViewer extends JInternalFrame
 {
@@ -189,24 +195,25 @@ public class GStructureViewer extends JInternalFrame
         userColour_actionPerformed(actionEvent);
       }
     });
-    jmolColour.setSelected(false);
-    jmolColour.setText(MessageManager.getString("label.colour_with_jmol"));
-    jmolColour.setToolTipText(MessageManager
+    viewerColour.setSelected(false);
+    viewerColour
+            .setText(MessageManager.getString("label.colour_with_jmol"));
+    viewerColour.setToolTipText(MessageManager
             .getString("label.let_jmol_manage_structure_colours"));
-    jmolColour.addActionListener(new ActionListener()
+    viewerColour.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent actionEvent)
       {
-        jmolColour_actionPerformed(actionEvent);
+        viewerColour_actionPerformed(actionEvent);
       }
     });
     helpMenu.setText(MessageManager.getString("action.help"));
-    jmolHelp.setText(MessageManager.getString("label.jmol_help"));
-    jmolHelp.addActionListener(new ActionListener()
+    helpItem.setText(MessageManager.getString("label.jmol_help"));
+    helpItem.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent actionEvent)
       {
-        jmolHelp_actionPerformed(actionEvent);
+        showHelp_actionPerformed(actionEvent);
       }
     });
     alignStructs
@@ -218,12 +225,12 @@ public class GStructureViewer extends JInternalFrame
         alignStructs_actionPerformed(actionEvent);
       }
     });
-    jmolActionMenu.setText(MessageManager.getString("label.jmol"));
+    viewerActionMenu.setText(MessageManager.getString("label.jmol"));
     menuBar.add(fileMenu);
     menuBar.add(viewMenu);
     menuBar.add(colourMenu);
-    menuBar.add(jmolActionMenu);
-    jmolActionMenu.setVisible(false);
+    menuBar.add(viewerActionMenu);
+    viewerActionMenu.setVisible(false);
     menuBar.add(helpMenu);
     fileMenu.add(savemenu);
     fileMenu.add(viewMapping);
@@ -244,7 +251,7 @@ public class GStructureViewer extends JInternalFrame
     colourMenu.add(buriedColour);
     colourMenu.add(purinePyrimidineColour);
     colourMenu.add(userColour);
-    colourMenu.add(jmolColour);
+    colourMenu.add(viewerColour);
     colourMenu.add(backGround);
 
     colourButtons.add(seqColour);
@@ -258,13 +265,13 @@ public class GStructureViewer extends JInternalFrame
     colourButtons.add(turnColour);
     colourButtons.add(buriedColour);
     colourButtons.add(userColour);
-    colourButtons.add(jmolColour);
+    colourButtons.add(viewerColour);
 
-    helpMenu.add(jmolHelp);
-    jmolActionMenu.add(alignStructs);
+    helpMenu.add(helpItem);
+    viewerActionMenu.add(alignStructs);
   }
 
-  protected void jmolColour_actionPerformed(ActionEvent actionEvent)
+  protected void viewerColour_actionPerformed(ActionEvent actionEvent)
   {
   }
 
@@ -276,7 +283,7 @@ public class GStructureViewer extends JInternalFrame
 
   JMenu fileMenu = new JMenu();
 
-  JMenu savemenu = new JMenu();
+  protected JMenu savemenu = new JMenu();
 
   JMenuItem pdbFile = new JMenuItem();
 
@@ -294,7 +301,7 @@ public class GStructureViewer extends JInternalFrame
 
   protected JMenu colourMenu = new JMenu();
 
-  protected JMenu jmolActionMenu = new JMenu();
+  protected JMenu viewerActionMenu = new JMenu();
 
   protected JMenuItem alignStructs = new JMenuItem();
 
@@ -324,13 +331,13 @@ public class GStructureViewer extends JInternalFrame
 
   protected JRadioButtonMenuItem userColour = new JRadioButtonMenuItem();
 
-  protected JRadioButtonMenuItem jmolColour = new JRadioButtonMenuItem();
+  protected JRadioButtonMenuItem viewerColour = new JRadioButtonMenuItem();
 
   protected ButtonGroup colourButtons = new ButtonGroup();
 
   JMenu helpMenu = new JMenu();
 
-  JMenuItem jmolHelp = new JMenuItem();
+  protected JMenuItem helpItem = new JMenuItem();
 
   public void pdbFile_actionPerformed(ActionEvent actionEvent)
   {
@@ -417,7 +424,7 @@ public class GStructureViewer extends JInternalFrame
 
   }
 
-  public void jmolHelp_actionPerformed(ActionEvent actionEvent)
+  public void showHelp_actionPerformed(ActionEvent actionEvent)
   {
 
   }
index 175a249..ac2897d 100644 (file)
@@ -360,11 +360,13 @@ public class StructureSelectionManager
               + maxChain.residues.size() + "\n\n");
       PrintStream ps = new PrintStream(System.out)
       {
+        @Override
         public void print(String x)
         {
           mappingDetails.append(x);
         }
 
+        @Override
         public void println()
         {
           mappingDetails.append("\n");