X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FChimeraViewFrame.java;h=fda4afb4da195e65b61f91aef66de14bded0f0c0;hb=5d59bb58f5bcecc6b240d125e13bbe1f1868f681;hp=a3ff00b5198bc0d428fbb03f7892d773fc785023;hpb=ae216fceddd8539d20fa5425cdaef3da73aba8f0;p=jalview.git diff --git a/src/jalview/gui/ChimeraViewFrame.java b/src/jalview/gui/ChimeraViewFrame.java index a3ff00b..fda4afb 100644 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@ -1,6 +1,6 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) - * Copyright (C) 2014 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * @@ -20,32 +20,6 @@ */ package jalview.gui; -import jalview.api.SequenceStructureBinding; -import jalview.api.structures.JalviewStructureDisplayI; -import jalview.bin.Cache; -import jalview.datamodel.Alignment; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.ColumnSelection; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.gui.ViewSelectionMenu.ViewSetProvider; -import jalview.io.AppletFormatAdapter; -import jalview.io.JalviewFileChooser; -import jalview.io.JalviewFileView; -import jalview.jbgui.GStructureViewer; -import jalview.schemes.BuriedColourScheme; -import jalview.schemes.ColourSchemeI; -import jalview.schemes.HelixColourScheme; -import jalview.schemes.HydrophobicColourScheme; -import jalview.schemes.PurinePyrimidineColourScheme; -import jalview.schemes.StrandColourScheme; -import jalview.schemes.TaylorColourScheme; -import jalview.schemes.TurnColourScheme; -import jalview.schemes.ZappoColourScheme; -import jalview.util.MessageManager; -import jalview.util.Platform; - -import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -54,9 +28,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; @@ -71,80 +45,78 @@ import javax.swing.event.InternalFrameEvent; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; +import jalview.bin.Cache; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.ext.rbvi.chimera.JalviewChimeraBinding; +import jalview.io.AppletFormatAdapter; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.schemes.BuriedColourScheme; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.HelixColourScheme; +import jalview.schemes.HydrophobicColourScheme; +import jalview.schemes.PurinePyrimidineColourScheme; +import jalview.schemes.StrandColourScheme; +import jalview.schemes.TaylorColourScheme; +import jalview.schemes.TurnColourScheme; +import jalview.schemes.ZappoColourScheme; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.ws.dbsources.Pdb; + /** * GUI elements for handlnig an external chimera display * * @author jprocter * */ -public class ChimeraViewFrame extends GStructureViewer implements Runnable, - ViewSetProvider, JalviewStructureDisplayI - +public class ChimeraViewFrame extends StructureViewerBase { - JalviewChimeraBindingModel jmb; + private JalviewChimeraBinding jmb; - AlignmentPanel ap; + private boolean allChainsSelected = false; - Vector atomsPicked = new Vector(); + private boolean alignAddedStructures = false; + + /* + * state flag for PDB retrieval thread + */ + private boolean _started = false; private boolean addingStructures = false; - ViewSelectionMenu seqColourBy; + private IProgressIndicator progressBar = null; + + /* + * pdb retrieval thread. + */ + private Thread worker = null; + + /* + * Path to Chimera session file. This is set when an open Jalview/Chimera + * session is saved, or on restore from a Jalview project (if it holds the + * filename of any saved Chimera sessions). + */ + private String chimeraSessionFile = 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(); @@ -154,10 +126,13 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, _alignwith = new Vector(); } - seqColourBy = new ViewSelectionMenu("Colour by ..", this, _colourwith, + // 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 +142,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("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 +160,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 +179,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 +200,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,42 +211,49 @@ 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. ap.getStructureSelectionManager().setMapping(seq, chains, alreadyMapped, AppletFormatAdapter.FILE); - if (ap.seqPanel.seqCanvas.fr != null) + if (ap.getSeqPanel().seqCanvas.fr != null) { - ap.seqPanel.seqCanvas.fr.featuresAdded(); + ap.getSeqPanel().seqCanvas.fr.featuresAdded(); 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.getPdbCount(); pe++) { - if (topJmol.jmb.pdbentry[pe].getFile().equals(alreadyMapped)) + if (topView.jmb.getPdbEntry(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.buildActionMenu(); ap.getStructureSelectionManager() .sequenceColoursChanged(ap); break; @@ -287,40 +266,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 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; @@ -336,24 +312,23 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, jmb.setColourBySequence(true); setSize(400, 400); // probably should be a configurable/dynamic default here initMenus(); - worker = null; - { - addingStructures = false; - worker = new Thread(this); - worker.start(); - } + + addingStructures = false; + worker = new Thread(this); + worker.start(); + this.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameClosing(InternalFrameEvent internalFrameEvent) { - closeViewer(); + closeViewer(false); } }); } /** - * 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,142 +338,45 @@ 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 _aps = new ArrayList(); - - public AlignmentPanel[] getAllAlignmentPanels() - { - AlignmentPanel[] t, list = new AlignmentPanel[0]; - for (String setid : _aps) - { - AlignmentPanel[] panels = PaintRefresher.getAssociatedPanels(setid); - if (panels != null) - { - t = new AlignmentPanel[list.length + panels.length]; - System.arraycopy(list, 0, t, 0, list.length); - System.arraycopy(panels, 0, t, list.length, panels.length); - list = t; - } - } - - return list; - } - - /** - * list of alignment panels to use for superposition - */ - Vector _alignwith = new Vector(); - - /** - * list of alignment panels that are used for colouring structures by aligned - * sequences - */ - Vector _colourwith = new Vector(); - - /** - * set the primary alignmentPanel reference and add another alignPanel to the - * list of ones to use for colouring and aligning + * Create a new viewer from saved session state data including Chimera session + * file. * - * @param nap - */ - public void addAlignmentPanel(AlignmentPanel nap) - { - if (ap == null) - { - ap = nap; - } - if (!_aps.contains(nap.av.getSequenceSetId())) - { - _aps.add(nap.av.getSequenceSetId()); - } - } - - /** - * remove any references held to the given alignment panel + * @param chimeraSession * - * @param nap + * @param alignPanel + * @param pdbArray + * @param seqsArray + * @param colourByChimera + * @param colourBySequence */ - public void removeAlignmentPanel(AlignmentPanel nap) + public ChimeraViewFrame(String chimeraSession, AlignmentPanel alignPanel, + PDBEntry[] pdbArray, + SequenceI[][] seqsArray, boolean colourByChimera, + boolean colourBySequence) { - try + super(); + this.chimeraSessionFile = chimeraSession; + openNewChimera(alignPanel, pdbArray, seqsArray); + if (colourByChimera) { - _alignwith.remove(nap); - _colourwith.remove(nap); - if (ap == nap) - { - ap = null; - for (AlignmentPanel aps : getAllAlignmentPanels()) - { - if (aps != nap) - { - ap = aps; - break; - } - } - } - } catch (Exception ex) - { - } - if (ap != null) - { - buildChimeraActionMenu(); - } - } - - public void useAlignmentPanelForSuperposition(AlignmentPanel nap) - { - addAlignmentPanel(nap); - if (!_alignwith.contains(nap)) - { - _alignwith.add(nap); - } - } - - public void excludeAlignmentPanelForSuperposition(AlignmentPanel nap) - { - if (_alignwith.contains(nap)) - { - _alignwith.remove(nap); - } - } - - public void useAlignmentPanelForColourbyseq(AlignmentPanel nap, - boolean enableColourBySeq) - { - useAlignmentPanelForColourbyseq(nap); - jmb.setColourBySequence(enableColourBySeq); - seqColour.setSelected(enableColourBySeq); - jmolColour.setSelected(!enableColourBySeq); - } - - public void useAlignmentPanelForColourbyseq(AlignmentPanel nap) - { - addAlignmentPanel(nap); - if (!_colourwith.contains(nap)) - { - _colourwith.add(nap); + jmb.setColourBySequence(false); + seqColour.setSelected(false); + viewerColour.setSelected(true); } - } - - public void excludeAlignmentPanelForColourbyseq(AlignmentPanel nap) - { - if (_colourwith.contains(nap)) + else if (colourBySequence) { - _colourwith.remove(nap); + jmb.setColourBySequence(true); + seqColour.setSelected(true); + viewerColour.setSelected(false); } } /** - * 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,46 +432,58 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, return; } - private Vector getJmolsFor(AlignmentPanel ap2) + private List getChimeraWindowsFor(AlignmentPanel apanel) { - Vector otherJmols = new Vector(); - // Now this AppJmol is mapped to new sequences. We must add them to - // the exisiting array + List result = new ArrayList(); 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 (((StructureViewerBase) frame).isLinkedWith(apanel)) { - otherJmols.addElement(topJmol); + result.add((ChimeraViewFrame) frame); } } } - return otherJmols; + return result; } - void initChimera(String command) + /** + * Launch Chimera. If we have a chimera session file name, send Chimera the + * command to open its saved session file. + */ + void initChimera() { 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("Chimera", true), getBounds().width, getBounds().height); - if (command == null) + + /* + * Pass an empty 'command' to launch Chimera + */ + jmb.evalStateCommand("", false); + + if (this.chimeraSessionFile != null) { - command = ""; + boolean opened = jmb.openSession(chimeraSessionFile); + if (!opened) + { + System.err + .println("An error occurred opening Chimera session file " + + chimeraSessionFile); + } } - jmb.evalStateCommand(command); jmb.setFinishedInit(true); + + jmb.startChimeraListener(); } - void setChainMenuItems(Vector chains) + void setChainMenuItems(List chainNames) { chainMenu.removeAll(); - if (chains == null) + if (chainNames == null) { return; } @@ -607,7 +497,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 +508,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 +526,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 toshow = new ArrayList(); for (int i = 0; i < chainMenu.getItemCount(); i++) { if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) @@ -648,17 +536,39 @@ 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); } - public void closeViewer() + /** + * Close down this instance of Jalview's Chimera viewer, giving the user the + * option to close the associated Chimera window (process). They may wish to + * keep it open until they have had an opportunity to save any work. + * + * @param closeChimera + * if true, close any linked Chimera process; if false, prompt first + */ + public void closeViewer(boolean closeChimera) { - jmb.closeViewer(); - ap = null; + if (jmb.isChimeraRunning()) + { + if (!closeChimera) + { + String prompt = MessageManager.formatMessage( + "label.confirm_close_chimera", new Object[] + { jmb.getViewerTitle("Chimera", false) }); + prompt = JvSwingUtils.wrapTooltip(true, prompt); + int confirm = JOptionPane.showConfirmDialog(this, prompt, + MessageManager.getString("label.close_viewer"), + JOptionPane.YES_NO_OPTION); + closeChimera = confirm == JOptionPane.YES_OPTION; + } + jmb.closeViewer(closeChimera); + } + setAlignmentPanel(null); _aps.clear(); _alignwith.clear(); _colourwith.clear(); @@ -668,72 +578,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 fileToLoad=new ArrayList(); + // todo - record which pdbids were successfully imported. + StringBuilder errormsgs = new StringBuilder(128); + StringBuilder files = new StringBuilder(128); List filePDB = new ArrayList(); - List filePDBpos =new ArrayList(); + List filePDBpos = new ArrayList(); + 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++) + for (int pi = 0; pi < jmb.getPdbCount(); pi++) { - String file = new File(jmb.pdbentry[pi].getFile()) - .getAbsoluteFile().getPath(); - if (file == null) + String file = null; + thePdbEntry = jmb.getPdbEntry(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) - { - progressBar.setProgressBar("Fetching PDB " + 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("Finished.", hdl); - } - if (pdbseq != null) + /* + * Retrieve PDB data, save to file, attach to PDBEntry + */ + file = fetchPdbFile(thePdbEntry); + if (file == 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 { + /* + * 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. @@ -746,50 +629,48 @@ 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) { try { - initChimera(""); + initChimera(); } catch (Exception ex) { Cache.log.error("Couldn't open Chimera viewer!", ex); } - } - int num=-1; + } + int num = -1; for (PDBEntry pe : filePDB) { num++; @@ -797,26 +678,25 @@ 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()); + jmb.addSequence(pos, jmb.getSequence()[pos]); + 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.getSsm().setMapping(jmb.getSequence()[pos], null, + pe.getFile(), + protocol); } catch (OutOfMemoryError oomerror) { new OOMWarning( @@ -832,10 +712,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) { @@ -844,13 +723,13 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, // do superposition if asked to if (alignAddedStructures) { - javax.swing.SwingUtilities.invokeLater(new Runnable() + new Thread(new Runnable() { public void run() { alignStructs_withAllAlignPanels(); } - }); + }).start(); alignAddedStructures = false; } addingStructures = false; @@ -859,24 +738,79 @@ 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( + pdbid + + " " + + 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(pdbseq.getSequenceAt(0).getPDBId() + .elementAt(0).getFile()).getAbsolutePath(); + processingEntry.setFile(filePath); + } + return filePath; + } + + @Override public void pdbFile_actionPerformed(ActionEvent actionEvent) { JalviewFileChooser chooser = new JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY")); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle("Save PDB File"); + chooser.setDialogTitle(MessageManager.getString("label.save_pdb_file")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(this); 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)); @@ -892,18 +826,31 @@ 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(); try { - for (int pdbe = 0; pdbe < jmb.pdbentry.length; pdbe++) + for (int pdbe = 0; pdbe < jmb.getPdbCount(); pdbe++) { - cap.appendText(jmb.printMapping(jmb.pdbentry[pdbe].getFile())); + cap.appendText(jmb.printMapping(jmb.getPdbEntry(pdbe).getFile())); cap.appendText("\n"); } } catch (OutOfMemoryError e) @@ -919,37 +866,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("EPS Generation not yet 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("PNG Generation not yet 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()); @@ -961,96 +904,110 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, { if (!jmb.isLoadingFromArchive()) { - if (_colourwith.size() == 0 && ap != null) + if (_colourwith.size() == 0 && getAlignmentPanel() != null) { // Make the currently displayed alignment panel the associated view - _colourwith.add(ap.alignFrame.alignPanel); + _colourwith.add(getAlignmentPanel().alignFrame.alignPanel); } } // Set the colour using the current view for the associated alignframe for (AlignmentPanel ap : _colourwith) { - jmb.colourBySequence(ap.av.showSequenceFeatures, ap); + jmb.colourBySequence(ap.av.isShowSequenceFeatures(), ap); } } } + @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, - "Select Background 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 { @@ -1061,17 +1018,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } - String viewId = null; - - public String getViewId() - { - if (viewId == null) - { - viewId = System.currentTimeMillis() + "." + this.hashCode(); - } - return viewId; - } - public void updateTitleAndMenus() { if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0) @@ -1079,12 +1025,12 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, repaint(); return; } - setChainMenuItems(jmb.chainNames); + setChainMenuItems(jmb.getChainNames()); - this.setTitle(jmb.getViewerTitle()); - if (jmb.getPdbFile().length > 1 && jmb.sequence.length > 1) + this.setTitle(jmb.getViewerTitle("Chimera", true)); + if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1) { - jmolActionMenu.setVisible(true); + viewerActionMenu.setVisible(true); } if (!jmb.isLoadingFromArchive()) { @@ -1092,27 +1038,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } - protected void buildChimeraActionMenu() - { - if (_alignwith == null) - { - _alignwith = new Vector(); - } - if (_alignwith.size() == 0 && ap != null) - { - _alignwith.add(ap); - } - ; - for (Component c : jmolActionMenu.getMenuComponents()) - { - if (c != alignStructs) - { - jmolActionMenu.remove((JMenuItem) c); - } - } - final ItemListener handler; - } - /* * (non-Javadoc) * @@ -1128,14 +1053,14 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, private void alignStructs_withAllAlignPanels() { - if (ap == null) + if (getAlignmentPanel() == null) { return; } ; if (_alignwith.size() == 0) { - _alignwith.add(ap); + _alignwith.add(getAlignmentPanel()); } ; try @@ -1187,42 +1112,40 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, return ap; } } - return ap; - } - - /** - * - * @param ap2 - * @return true if this Jmol instance is linked with the given alignPanel - */ - public boolean isLinkedWith(AlignmentPanel ap2) - { - return _aps.contains(ap2.av.getSequenceSetId()); - } - - public boolean isUsedforaligment(AlignmentPanel ap2) - { - - return (_alignwith != null) && _alignwith.contains(ap2); + return getAlignmentPanel(); } - public boolean isUsedforcolourby(AlignmentPanel ap2) + @Override + public AAStructureBindingModel getBinding() { - return (_colourwith != null) && _colourwith.contains(ap2); + return jmb; } /** + * Ask Chimera to save its session to the designated file path. Returns true + * if successful, else false. * - * @return TRUE if the view is NOT being coloured by sequence associations. + * @param filepath + * @see getStateInfo */ - public boolean isColouredByJmol() + public boolean saveSession(String filepath) { - return !jmb.isColourBySequence(); + boolean result = jmb.saveSession(filepath); + if (result) + { + this.chimeraSessionFile = filepath; + } + return result; } - public SequenceStructureBinding getBinding() + /** + * Returns the file path of the Chimera session file the last time it was + * saved. If it was never saved, returns an empty string. There is no + * guarantee that the Chimera session has not changed since it was saved. + */ + @Override + public String getStateInfo() { - return jmb; + return this.chimeraSessionFile; } - }