import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
* Select something in Chimera
*
* @param command
- * the selection command to pass to Chimera
+ * the selection command to pass to Chimera
*/
public void select(String command)
{
/**
* Return the list of depiction presets available from within Chimera. Chimera
- * will return the list as a series of lines with the format: Preset type
- * number "description"
+ * will return the list as a series of lines with the format: Preset type number
+ * "description"
*
* @return list of presets
*/
}
/**
- * Launch Chimera, unless an instance linked to this object is already
- * running. Returns true if chimera is successfully launched, or already
- * running, else false.
+ * Launch Chimera, unless an instance linked to this object is already running.
+ * Returns true if chimera is successfully launched, or already running, else
+ * false.
*
* @param chimeraPaths
* @return
* Determine the color that Chimera is using for this model.
*
* @param model
- * the ChimeraModel we want to get the Color for
+ * the ChimeraModel we want to get the Color for
* @return the default model Color for this model in Chimera
*/
public Color getModelColor(ChimeraModel model)
/**
*
* Get information about the residues associated with a model. This uses the
- * Chimera listr command. We don't return the resulting residues, but we add
- * the residues to the model.
+ * Chimera listr command. We don't return the resulting residues, but we add the
+ * residues to the model.
*
* @param model
- * the ChimeraModel to get residue information for
+ * the ChimeraModel to get residue information for
*
*/
public void addResidues(ChimeraModel model)
* Send a command to Chimera.
*
* @param command
- * Command string to be send.
+ * Command string to be send.
* @param reply
- * Flag indicating whether the method should return the reply from
- * Chimera or not.
+ * Flag indicating whether the method should return the reply
+ * from Chimera or not.
* @return List of Strings corresponding to the lines in the Chimera reply or
* <code>null</code>.
*/
*/
int waited = 0;
int pause = 25;
- while (busy && waited < 1001)
+ while (busy && waited < 1001)
{
try
{
String method = getHttpRequestMethod();
if ("GET".equals(method))
{
- command = command.replace(" ", "+").replace("#", "%23")
- .replace("|", "%7C").replace(";", "%3B");
+ try
+ {
+ command = URLEncoder.encode(command, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e)
+ {
+ command = command.replace(" ", "+").replace("#", "%23")
+ .replace("|", "%7C").replace(";", "%3B")
+ .replace(":", "%3A");
+ }
}
commands.add(new BasicNameValuePair("command", command));
* 0.93 is ChimeraX latest, 1.0 expected soon
*/
private static String[] CHIMERA_VERSIONS = new String[] { "1.16.2",
- "1.16.1", "1.16",
- "1.15.2", "1.15.1", "1.15", "1.14.2", "1.14.1", "1.14",
- "1.13.1", "1.13", "1.12.2", "1.12.1", "1.12", "1.11.2",
+ "1.16.1", "1.16", "1.15.2", "1.15.1", "1.15", "1.14.2", "1.14.1",
+ "1.14", "1.13.1", "1.13", "1.12.2", "1.12.1", "1.12", "1.11.2",
"1.11.2", "1.11.1", "1.11" };
- private static String[] CHIMERAX_VERSIONS = new String[] { "1.0", "0.93",
- "0.92", "0.91", "0.9" };
+ // Missing 1.1 as this has known bug see JAL-2422
+ private static String[] CHIMERAX_VERSIONS = new String[] { "1.2.5", "1.0",
+ "0.93", "0.92", "0.91", "0.9" };
static final String[] defaultStructureKeys = { "Structure", "pdb",
"pdbFileName", "PDB ID", "structure", "biopax.xref.PDB", "pdb_ids",
/**
* This is called by the selectionListener to let us know that the user has
- * changed their selection in Chimera. We need to go back to Chimera to find
- * out what is currently selected and update our list.
+ * changed their selection in Chimera. We need to go back to Chimera to find out
+ * what is currently selected and update our list.
*/
public void chimeraSelectionChanged()
{
}
/**
- * Add a selection to the selection list. This is called primarily by the
- * Model Navigator Dialog to keep the selections in sync
+ * Add a selection to the selection list. This is called primarily by the Model
+ * Navigator Dialog to keep the selections in sync
*
* @param selectionToAdd
- * the selection to add to our list
+ * the selection to add to our list
*/
public void addChimSelection(ChimeraStructuralObject selectionToAdd)
{
* Model Navigator Dialog to keep the selections in sync
*
* @param selectionToRemove
- * the selection to remove from our list
+ * the selection to remove from our list
*/
public void removeChimSelection(ChimeraStructuralObject selectionToRemove)
{
// }
// }
- /*
- * Jalview addition: check if path set in user preferences
- */
+ String os = System.getProperty("os.name");
String userPath = Cache
.getDefault(isChimeraX ? Preferences.CHIMERAX_PATH
: Preferences.CHIMERA_PATH, null);
- if (userPath != null)
- {
- pathList.add(userPath);
- }
/*
* paths are based on getChimeraPaths() in
String chimera = isChimeraX ? "ChimeraX" : "Chimera";
String chimeraExe = isChimeraX ? "ChimeraX" : "chimera";
+ /*
+ * Jalview addition: check if path set in user preferences
+ */
+ if (userPath != null)
+ {
+ // in macos, deal with the user selecting the .app folder
+ boolean adjusted = false;
+ if (os.startsWith("Mac") && userPath.endsWith((".app")))
+ {
+ String possiblePath = String.format("%s/Contents/MacOS/%s",
+ userPath, chimeraExe);
+ if (new File(possiblePath).exists())
+ {
+ pathList.add(possiblePath);
+ adjusted = true;
+ }
+ }
+ if (!adjusted)
+ {
+ pathList.add(userPath);
+ }
+ }
+
// Add default installation paths
- String os = System.getProperty("os.name");
if (os.startsWith("Linux"))
{
- // todo should this be /chimeraX/ for ChimeraX? not in structureVizX code
- pathList.add("/usr/local/chimera/bin/" + chimeraExe);
- pathList.add("/usr/local/bin/" + chimeraExe);
- pathList.add("/usr/bin/" + chimeraExe);
- pathList.add(System.getProperty("user.home") + "/opt/bin/" + chimeraExe);
+ // ChimeraX .deb and .rpm packages put symbolic link from /usr/bin/chimerax
+ pathList.add(String.format("/usr/bin/%s", chimeraExe.toLowerCase()));
+ pathList.add(String.format("/usr/bin/%s", chimeraExe));
+
+ pathList.add(
+ String.format("/usr/local/bin/%s", chimeraExe.toLowerCase()));
+ pathList.add(String.format("/usr/local/bin/%s", chimeraExe));
+
+ // these paths also used by .deb and .rpm
+ pathList.add(String.format("/usr/lib/ucsf-%s/bin/%s",
+ chimera.toLowerCase(), chimeraExe));
+ pathList.add(String.format("/usr/libexec/UCSF-%s/bin/%s", chimera,
+ chimeraExe));
+
+ pathList.add(String.format("/usr/local/chimera/bin/%s", chimeraExe));
+
+ // user home paths
+ pathList.add(String.format("%s/bin/%s",
+ System.getProperty("user.home"), chimeraExe.toLowerCase()));
+ pathList.add(String.format("%s/bin/%s",
+ System.getProperty("user.home"), chimeraExe));
+ pathList.add(String.format("%s/opt/bin/%s",
+ System.getProperty("user.home"), chimeraExe.toLowerCase()));
+ pathList.add(String.format("%s/opt/bin/%s",
+ System.getProperty("user.home"), chimeraExe));
+ pathList.add(String.format("%s/local/bin/%s",
+ System.getProperty("user.home"), chimeraExe.toLowerCase()));
+ pathList.add(String.format("%s/local/bin/%s",
+ System.getProperty("user.home"), chimeraExe));
}
else if (os.startsWith("Windows"))
{
pathList.add(path);
pathList.add(path + ".exe");
}
+ // try without a version number too
+ String path = String.format("%s\\%s\\bin\\%s", root, chimera,
+ chimeraExe);
+ pathList.add(path);
+ pathList.add(path + ".exe");
}
}
else if (os.startsWith("Mac"))
{
+ // check for installations with version numbers first
+ String[] candidates = isChimeraX ? CHIMERAX_VERSIONS
+ : CHIMERA_VERSIONS;
+ for (String version : candidates)
+ {
+ pathList.add(
+ String.format("/Applications/%s-%s.app/Contents/MacOS/%s",
+ chimera, version, chimeraExe));
+ }
pathList.add(String.format("/Applications/%s.app/Contents/MacOS/%s",
chimera, chimeraExe));
}
}
/**
- * Loads properties from the given properties file. Any existing properties
- * are first cleared.
+ * Loads properties from the given properties file. Any existing properties are
+ * first cleared.
*/
public static void loadProperties(String propsFile)
{
}
/**
- * Gets Jalview application property of given key. Returns null if key not
- * found
+ * Gets Jalview application property of given key. Returns null if key not found
*
* @param key
- * Name of property
+ * Name of property
*
* @return Property value
*/
}
/**
- * These methods are used when checking if the saved preference is different
- * to the default setting
+ * These methods are used when checking if the saved preference is different to
+ * the default setting
*/
public static boolean getDefault(String property, boolean def)
}
/**
- * Answers the value of the given property, or the supplied default value if
- * the property is not set
+ * Answers the value of the given property, or the supplied default value if the
+ * property is not set
*/
public static String getDefault(String property, String def)
{
* Stores property in the file "HOME_DIR/.jalview_properties"
*
* @param key
- * Name of object
+ * Name of object
* @param obj
- * String value of property
+ * String value of property
*
* @return previous value of property (or null)
*/
* Loads in user colour schemes from files.
*
* @param files
- * a '|'-delimited list of file paths
+ * a '|'-delimited list of file paths
*/
public static void initUserColourSchemes(String files)
{
// open Preferences -> Connections
String message = MessageManager
.getString("label.proxy_password_required");
- Preferences.openPreferences(Preferences.CONNECTIONS_TAB,
- message);
+ Preferences.openPreferences(
+ Preferences.TabRef.CONNECTIONS_TAB, message);
Preferences.getInstance()
.proxyAuthPasswordCheckHighlight(true, true);
}
public class ChimeraXCommands extends ChimeraCommands
{
// https://www.cgl.ucsf.edu/chimerax/docs/user/commands/info.html#resattr
- private static final StructureCommand LIST_RESIDUE_ATTRIBUTES = new StructureCommand("info resattr");
+ private static final StructureCommand LIST_RESIDUE_ATTRIBUTES = new StructureCommand(
+ "info resattr");
// https://www.cgl.ucsf.edu/chimerax/docs/user/commands/exit.html
- private static final StructureCommand CLOSE_CHIMERAX = new StructureCommand("exit");
+ private static final StructureCommand CLOSE_CHIMERAX = new StructureCommand(
+ "exit");
// https://www.cgl.ucsf.edu/chimerax/docs/user/commands/info.html#notify
- private static final StructureCommand STOP_NOTIFY_SELECTION = new StructureCommand("info notify stop selection jalview");
+ private static final StructureCommand STOP_NOTIFY_SELECTION = new StructureCommand(
+ "info notify stop selection jalview");
- private static final StructureCommand STOP_NOTIFY_MODELS = new StructureCommand("info notify stop models jalview");
+ private static final StructureCommand STOP_NOTIFY_MODELS = new StructureCommand(
+ "info notify stop models jalview");
// https://www.cgl.ucsf.edu/chimerax/docs/user/commands/info.html#selection
private static final StructureCommand GET_SELECTION = new StructureCommand(
}
/**
- * Returns a viewer command to set the given residue attribute value on
- * residues specified by the AtomSpecModel, for example
+ * Returns a viewer command to set the given residue attribute value on residues
+ * specified by the AtomSpecModel, for example
*
* <pre>
* setattr #0/A:3-9,14-20,39-43 res jv_strand 'strand' create true
* Returns the range(s) formatted as a ChimeraX atomspec, for example
* <p>
* #1/A:2-20,30-40/B:10-20|#2/A:12-30
+ * <p>
+ * Note there is no need to explicitly exclude ALTLOC atoms when
+ * {@code alphaOnly == true}, as this is the default behaviour of ChimeraX (a
+ * change from Chimera)
*
* @return
*/
// TODO @P if RNA - add nucleotide flag to AtomSpecModel?
sb.append("@CA");
}
- // todo: is there ChimeraX syntax to exclude altlocs?
}
return sb.toString();
}
public List<StructureCommandI> startNotifications(String uri)
{
List<StructureCommandI> cmds = new ArrayList<>();
- cmds.add(new StructureCommand("info notify start models jalview prefix ModelChanged url " + uri));
- cmds.add(new StructureCommand("info notify start selection jalview prefix SelectionChanged url " + uri));
+ cmds.add(new StructureCommand(
+ "info notify start models jalview prefix ModelChanged url "
+ + uri));
+ cmds.add(new StructureCommand(
+ "info notify start selection jalview prefix SelectionChanged url "
+ + uri));
return cmds;
}
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import javax.help.HelpSetException;
import javax.swing.JComboBox;
/**
* Holds name and link separated with | character. Sequence IDS and Sequences
- * must be $SEQUENCEIDS$ or $SEQUENCEIDS=/.possible | chars ./=$ and
- * $SEQUENCES$ or $SEQUENCES=/.possible | chars ./=$ and separation character
- * for first and second token specified after a pipe character at end |,|.
- * (TODO: proper escape for using | to separate ids or sequences
+ * must be $SEQUENCEIDS$ or $SEQUENCEIDS=/.possible | chars ./=$ and $SEQUENCES$
+ * or $SEQUENCES=/.possible | chars ./=$ and separation character for first and
+ * second token specified after a pipe character at end |,|. (TODO: proper
+ * escape for using | to separate ids or sequences
*/
public static List<String> groupURLLinks;
public static void openPreferences()
{
- openPreferences(0, null);
+ openPreferences(null, null);
}
- public static void openPreferences(int selectTab, String message)
+ public static void openPreferences(TabRef selectTab, String message)
{
Preferences p = getInstance();
- p.selectTab(selectTab);
- p.setMessage(message);
+ if (selectTab != null)
+ p.selectTab(selectTab, message);
p.frame.show();
p.frame.moveToFront();
p.frame.grabFocus();
}
+ public void selectTab(TabRef selectTab, String message)
+ {
+ this.selectTab(selectTab);
+ if (message != null)
+ this.setMessage(message);
+ this.frame.show();
+ }
+
/**
* Creates a new Preferences object.
*/
}
/**
- * Do any necessary validation before saving settings. Return focus to the
- * first tab which fails validation.
+ * Do any necessary validation before saving settings. Return focus to the first
+ * tab which fails validation.
*
* @return
*/
* DOCUMENT ME!
*
* @param e
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
@Override
public void cancel_actionPerformed(ActionEvent e)
* DOCUMENT ME!
*
* @param e
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
@Override
public void annotations_actionPerformed(ActionEvent e)
}
/**
- * Returns true if structure viewer path is to a valid executable, else shows
- * an error dialog. Does nothing if the path is empty, as is the case for Jmol
+ * Returns true if structure viewer path is to a valid executable, else shows an
+ * error dialog. Does nothing if the path is empty, as is the case for Jmol
* (built in to Jalview) or when Jalview is left to try default paths.
*/
private boolean validateViewerPath()
}
/**
- * If Chimera or ChimeraX or Pymol is selected, check it can be found on
- * default or user-specified path, if not show a warning/help dialog
+ * If Chimera or ChimeraX or Pymol is selected, check it can be found on default
+ * or user-specified path, if not show a warning/help dialog
*/
@Override
protected void structureViewer_actionPerformed(String selectedItem)
MessageManager.getString("label.viewer_missing")),
"", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE,
null, options, options[0]);
+
if (showHelp == JvOptionPane.NO_OPTION)
{
+ this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
try
{
Help.showHelpWindow(HelpId.StructureViewer);
e.printStackTrace();
}
}
+ else if (showHelp == JvOptionPane.OK_OPTION)
+ {
+ this.selectTab(Preferences.TabRef.STRUCTURE_TAB, null);
+ CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
+ try
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ structureViewerPath.setBackground(Color.PINK);
+ Thread.sleep(500);
+ structureViewerPath.setBackground(Color.WHITE);
+ Thread.sleep(500);
+ }
+ } catch (InterruptedException e)
+ {
+ }
+ });
+ }
}
}
}
}
- public final static int CONNECTIONS_TAB = 5;
+ public static enum TabRef
+ {
+ CONNECTIONS_TAB, STRUCTURE_TAB
+ };
- public void selectTab(int selectTab)
+ public void selectTab(TabRef selectTab)
{
// select a given tab - currently only for Connections
switch (selectTab)
case CONNECTIONS_TAB:
tabbedPane.setSelectedComponent(connectTab);
break;
+ case STRUCTURE_TAB:
+ tabbedPane.setSelectedComponent(structureTab);
+ break;
default:
}
}
}
/**
- * Show a dialog for the user to choose a file. Returns the chosen path, or
- * null on Cancel.
+ * Show a dialog for the user to choose a file. Returns the chosen path, or null
+ * on Cancel.
*
* @return
*/
* DOCUMENT ME!
*
* @param e
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void ok_actionPerformed(ActionEvent e)
{
* DOCUMENT ME!
*
* @param e
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void cancel_actionPerformed(ActionEvent e)
{
* DOCUMENT ME!
*
* @param e
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void annotations_actionPerformed(ActionEvent e)
{