X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FChimeraViewFrame.java;h=3a17ea35bfeaa69b3551be289b53ce99988d936a;hb=b7cd96eaeb85474ee2ddec1de92181a3b88ceece;hp=1915936dc7ecdb137a88fbfc7a36c855ccb44c0a;hpb=3bc2fbe640abb0d8941aead117c9624dd16773a3;p=jalview.git diff --git a/src/jalview/gui/ChimeraViewFrame.java b/src/jalview/gui/ChimeraViewFrame.java index 1915936..3a17ea3 100644 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@ -22,55 +22,35 @@ package jalview.gui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.io.BufferedReader; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; 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.Collections; import java.util.List; import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.Vector; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JColorChooser; import javax.swing.JInternalFrame; import javax.swing.JMenu; import javax.swing.JMenuItem; -import javax.swing.JOptionPane; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; -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.api.AlignmentViewPanel; +import jalview.api.FeatureRenderer; +import jalview.bin.Console; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; +import jalview.datamodel.StructureViewerModel; +import jalview.datamodel.StructureViewerModel.StructureData; import jalview.ext.rbvi.chimera.JalviewChimeraBinding; -import jalview.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.gui.StructureViewer.ViewerType; +import jalview.io.DataSourceType; +import jalview.io.StructureFile; import jalview.structures.models.AAStructureBindingModel; +import jalview.util.ImageMaker.TYPE; import jalview.util.MessageManager; import jalview.util.Platform; -import jalview.ws.dbsources.Pdb; /** * GUI elements for handling an external chimera display @@ -82,24 +62,6 @@ public class ChimeraViewFrame extends StructureViewerBase { private JalviewChimeraBinding jmb; - private boolean allChainsSelected = false; - - private boolean alignAddedStructures = false; - - /* - * state flag for PDB retrieval thread - */ - private boolean _started = false; - - private boolean addingStructures = false; - - 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 @@ -107,259 +69,120 @@ public class ChimeraViewFrame extends StructureViewerBase */ private String chimeraSessionFile = null; - private Random random = new Random(); + private int myWidth = 500; - /** + private int myHeight = 150; + + private JMenuItem writeFeatures=null; + + private JMenu fetchAttributes=null; +/** * Initialise menu options. */ - private void initMenus() + @Override + protected 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()); - viewerColour.setSelected(!jmb.isColourBySequence()); - if (_colourwith == null) - { - _colourwith = new Vector(); - } - if (_alignwith == null) - { - _alignwith = new Vector(); - } - - // save As not yet implemented - savemenu.setVisible(false); + super.initMenus(); - ViewSelectionMenu seqColourBy = new ViewSelectionMenu( - MessageManager.getString("label.colour_by"), this, _colourwith, - new ItemListener() - { - @Override - public void itemStateChanged(ItemEvent e) - { - if (!seqColour.isSelected()) - { - seqColour.doClick(); - } - else - { - // update the Chimera display now. - seqColour_actionPerformed(null); - } - } - }); - viewMenu.add(seqColourBy); + savemenu.setVisible(false); // not yet implemented viewMenu.add(fitToWindow); - final ItemListener handler; - JMenu alpanels = new ViewSelectionMenu( - MessageManager.getString("label.superpose_with"), this, - _alignwith, handler = new ItemListener() - { - @Override - public void itemStateChanged(ItemEvent e) - { - alignStructs.setEnabled(_alignwith.size() > 0); - alignStructs.setToolTipText(MessageManager - .formatMessage( - "label.align_structures_using_linked_alignment_views", - new Object[] - { new Integer(_alignwith.size()).toString() })); - } - }); - handler.itemStateChanged(null); - viewerActionMenu.add(alpanels); - viewerActionMenu.addMenuListener(new MenuListener() + writeFeatures = new JMenuItem( + MessageManager.getString("label.create_viewer_attributes")); + writeFeatures.setToolTipText(MessageManager + .getString("label.create_viewer_attributes_tip")); + writeFeatures.addActionListener(new ActionListener() { - @Override - public void menuSelected(MenuEvent e) + public void actionPerformed(ActionEvent e) { - handler.itemStateChanged(null); + sendFeaturesToChimera(); } + }); + viewerActionMenu.add(writeFeatures); - @Override - public void menuDeselected(MenuEvent e) - { - // TODO Auto-generated method stub - } + fetchAttributes = new JMenu( + MessageManager.formatMessage("label.fetch_viewer_attributes",getViewerName())); + fetchAttributes.setToolTipText( + MessageManager.formatMessage("label.fetch_viewer_attributes_tip",getViewerName())); + fetchAttributes.addMouseListener(new MouseAdapter() + { @Override - public void menuCanceled(MenuEvent e) + public void mouseEntered(MouseEvent e) { - // TODO Auto-generated method stub + buildAttributesMenu(fetchAttributes); } }); + viewerActionMenu.add(fetchAttributes); } - + @Override + protected void buildActionMenu() + { + super.buildActionMenu(); + // add these back in after menu is refreshed + viewerActionMenu.add(writeFeatures); + viewerActionMenu.add(fetchAttributes); + + }; /** - * add a single PDB structure to a new or existing Chimera view + * Query the structure viewer for its residue attribute names and add them as + * items off the attributes menu * - * @param pdbentry - * @param seq - * @param chains - * @param ap + * @param attributesMenu */ - public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq, - String[] chains, final AlignmentPanel ap) + protected void buildAttributesMenu(JMenu attributesMenu) { - super(); - - /* - * is the pdb file already loaded? - */ - String pdbId = pdbentry.getId(); - String alreadyMapped = ap.getStructureSelectionManager() - .alreadyMappedToFile(pdbId); - - if (alreadyMapped != null) + List atts = jmb.getChimeraAttributes(); + attributesMenu.removeAll(); + Collections.sort(atts); + for (String attName : atts) { - int option = chooseAddSequencesToViewer(pdbId); - if (option == JOptionPane.CANCEL_OPTION) + JMenuItem menuItem = new JMenuItem(attName); + menuItem.addActionListener(new ActionListener() { - return; - } - if (option == JOptionPane.YES_OPTION) - { - addSequenceMappingsToStructure(seq, chains, ap, alreadyMapped); - return; - } - } - - /* - * Check if there are other Chimera views involving this alignment and give - * user the option to add and align this molecule to one of them - */ - List existingViews = getChimeraWindowsFor(ap); - for (ChimeraViewFrame view : existingViews) - { - // TODO: highlight view somehow - /* - * JAL-1742 exclude view with this structure already mapped (don't offer - * to align chain B to chain A of the same structure) - */ - if (view.hasPdbId(pdbId)) - { - continue; - } - int option = chooseAlignStructureToViewer(pdbId, view); - if (option == JOptionPane.CANCEL_OPTION) - { - return; - } - if (option == JOptionPane.YES_OPTION) - { - view.useAlignmentPanelForSuperposition(ap); - view.addStructure(pdbentry, seq, chains, true, ap.alignFrame); - return; - } + @Override + public void actionPerformed(ActionEvent e) + { + if (getBinding().copyStructureAttributesToFeatures(attName, + getAlignmentPanel()) > 0) + { + getAlignmentPanel().getFeatureRenderer().featuresAdded(); + } + } + }); + attributesMenu.add(menuItem); } - - /* - * If the options above are declined or do not apply, open a new viewer - */ - openNewChimera(ap, new PDBEntry[] - { pdbentry }, new SequenceI[][] - { seq }); - } - - /** - * Presents a dialog with the option to add an align a structure to an - * existing Chimera view - * - * @param pdbId - * @param view - * @return YES, NO or CANCEL JOptionPane code - */ - protected int chooseAlignStructureToViewer(String pdbId, - ChimeraViewFrame view) - { - int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop, - MessageManager.formatMessage("label.add_pdbentry_to_view", - new Object[] - { pdbId, view.getTitle() }), MessageManager - .getString("label.align_to_existing_structure_view"), - JOptionPane.YES_NO_CANCEL_OPTION); - return option; } /** - * Presents a dialog with the option to add sequences to a viewer which - * already has their structure open - * - * @param pdbId - * @return YES, NO or CANCEL JOptionPane code + * Sends command(s) to the structure viewer to create residue attributes for + * visible Jalview features */ - protected int chooseAddSequencesToViewer(String pdbId) + protected void sendFeaturesToChimera() { - int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop, - MessageManager.formatMessage( - "label.pdb_entry_is_already_displayed", new Object[] - { pdbId }), MessageManager.formatMessage( - "label.map_sequences_to_visible_window", new Object[] - { pdbId }), JOptionPane.YES_NO_CANCEL_OPTION); - return option; + // todo pull up? + int count = jmb.sendFeaturesToViewer(getAlignmentPanel()); + statusBar.setText( + MessageManager.formatMessage("label.attributes_set", count, getViewerName())); } /** - * Adds mappings for the given sequences to an already opened PDB structure, - * and updates any viewers that have the PDB file + * open a single PDB structure in a new Chimera view * + * @param pdbentry * @param seq * @param chains * @param ap - * @param pdbFilename */ - protected void addSequenceMappingsToStructure(SequenceI[] seq, - String[] chains, final AlignmentPanel ap, String pdbFilename) + public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq, + String[] chains, final AlignmentPanel ap) { - // TODO : Fix multiple seq to one chain issue here. - /* - * create the mappings - */ - ap.getStructureSelectionManager().setMapping(seq, chains, pdbFilename, - AppletFormatAdapter.FILE); + this(); - /* - * alert the FeatureRenderer to show new (PDB RESNUM) features - */ - if (ap.getSeqPanel().seqCanvas.fr != null) - { - ap.getSeqPanel().seqCanvas.fr.featuresAdded(); - ap.paintAlignment(true); - } - - /* - * add the sequences to any other Chimera viewers for this pdb file - */ - // JBPNOTE: this looks like a binding routine, rather than a gui routine - for (JInternalFrame frame : Desktop.instance.getAllFrames()) - { - if (frame instanceof ChimeraViewFrame) - { - ChimeraViewFrame chimeraView = ((ChimeraViewFrame) frame); - for (int pe = 0; pe < chimeraView.jmb.getPdbCount(); pe++) - { - if (chimeraView.jmb.getPdbEntry(pe).getFile().equals(pdbFilename)) - { - chimeraView.jmb.addSequence(pe, seq); - chimeraView.addAlignmentPanel(ap); - /* - * add it to the set of alignments used for colouring structure by - * sequence - */ - chimeraView.useAlignmentPanelForColourbyseq(ap); - chimeraView.buildActionMenu(); - ap.getStructureSelectionManager().sequenceColoursChanged(ap); - break; - } - } - } - } + openNewChimera(ap, new PDBEntry[] { pdbentry }, + new SequenceI[][] + { seq }); } /** @@ -367,34 +190,26 @@ public class ChimeraViewFrame extends StructureViewerBase */ protected void createProgressBar() { - if (progressBar == null) + if (getProgressIndicator() == null) { - progressBar = new ProgressBar(statusPanel, statusBar); + setProgressIndicator(new ProgressBar(statusPanel, statusBar)); } } - protected boolean hasPdbId(String pdbId) - { - return jmb.hasPdbId(pdbId); - } - private void openNewChimera(AlignmentPanel ap, PDBEntry[] pdbentrys, SequenceI[][] seqs) { createProgressBar(); - String[][] chains = extractChains(seqs); - jmb = new JalviewChimeraBindingModel(this, - ap.getStructureSelectionManager(), pdbentrys, seqs, chains, - null); + jmb = newBindingModel(ap, pdbentrys, seqs); addAlignmentPanel(ap); useAlignmentPanelForColourbyseq(ap); + if (pdbentrys.length > 1) { - alignAddedStructures = true; useAlignmentPanelForSuperposition(ap); } jmb.setColourBySequence(true); - setSize(400, 400); // probably should be a configurable/dynamic default here + setSize(myWidth, myHeight); initMenus(); addingStructures = false; @@ -403,7 +218,9 @@ public class ChimeraViewFrame extends StructureViewerBase this.addInternalFrameListener(new InternalFrameAdapter() { - public void internalFrameClosing(InternalFrameEvent internalFrameEvent) + @Override + public void internalFrameClosing( + InternalFrameEvent internalFrameEvent) { closeViewer(false); } @@ -411,65 +228,53 @@ public class ChimeraViewFrame extends StructureViewerBase } - /** - * Retrieve chains for sequences by inspecting their PDB refs. The hope is - * that the first will be to the sequence's own chain. Really need a more - * managed way of doing this. - * - * @param seqs - * @return - */ - protected String[][] extractChains(SequenceI[][] seqs) + protected JalviewChimeraBindingModel newBindingModel(AlignmentPanel ap, + PDBEntry[] pdbentrys, SequenceI[][] seqs) { - String[][] chains = new String[seqs.length][]; - for (int i = 0; i < seqs.length; i++) - { - chains[i] = new String[seqs[i].length]; - int seqno = 0; - for (SequenceI seq : seqs[i]) - { - String chain = null; - if (seq.getDatasetSequence() != null) - { - Vector pdbrefs = seq.getDatasetSequence().getPDBId(); - if (pdbrefs != null && pdbrefs.size() > 0) - { - chain = pdbrefs.get(0).getChainCode(); - } - } - chains[i][seqno++] = chain; - } - } - return chains; + return new JalviewChimeraBindingModel(this, + ap.getStructureSelectionManager(), pdbentrys, seqs, null); } /** * Create a new viewer from saved session state data including Chimera session - * file. - * - * @param chimeraSession + * file * + * @param chimeraSessionFile * @param alignPanel * @param pdbArray * @param seqsArray * @param colourByChimera * @param colourBySequence + * @param newViewId */ - public ChimeraViewFrame(String chimeraSession, AlignmentPanel alignPanel, - PDBEntry[] pdbArray, - SequenceI[][] seqsArray, boolean colourByChimera, - boolean colourBySequence) - { - super(); - this.chimeraSessionFile = chimeraSession; + public ChimeraViewFrame(StructureViewerModel viewerData, + AlignmentPanel alignPanel, String sessionFile, String vid) + { + this(); + setViewId(vid); + this.chimeraSessionFile = sessionFile; + Map pdbData = viewerData.getFileData(); + PDBEntry[] pdbArray = new PDBEntry[pdbData.size()]; + SequenceI[][] seqsArray = new SequenceI[pdbData.size()][]; + int i = 0; + for (StructureData data : pdbData.values()) + { + PDBEntry pdbentry = new PDBEntry(data.getPdbId(), null, + PDBEntry.Type.PDB, data.getFilePath()); + pdbArray[i] = pdbentry; + List sequencesForPdb = data.getSeqList(); + seqsArray[i] = sequencesForPdb + .toArray(new SequenceI[sequencesForPdb.size()]); + i++; + } openNewChimera(alignPanel, pdbArray, seqsArray); - if (colourByChimera) + if (viewerData.isColourByViewer()) { jmb.setColourBySequence(false); seqColour.setSelected(false); viewerColour.setSelected(true); } - else if (colourBySequence) + else if (viewerData.isColourWithAlignPanel()) { jmb.setColourBySequence(true); seqColour.setSelected(true); @@ -478,115 +283,34 @@ public class ChimeraViewFrame extends StructureViewerBase } /** - * create a new viewer containing several structures superimposed using the - * given alignPanel. + * create a new viewer containing several structures, optionally superimposed + * using the given alignPanel. * * @param pe * @param seqs * @param ap */ - public ChimeraViewFrame(PDBEntry[] pe, SequenceI[][] seqs, + public ChimeraViewFrame(PDBEntry[] pe, boolean alignAdded, + SequenceI[][] seqs, AlignmentPanel ap) { - super(); + this(); + setAlignAddedStructures(alignAdded); openNewChimera(ap, pe, seqs); } - public ChimeraViewFrame(Map> toView, - AlignmentPanel alignPanel) + /** + * Default constructor + */ + public ChimeraViewFrame() { super(); /* - * Convert the map of sequences per pdb entry into the tied arrays expected - * by openNewChimera - * - * TODO pass the Map down to openNewChimera and its callees instead + * closeViewer will decide whether or not to close this frame + * depending on whether user chooses to Cancel or not */ - final Set pdbEntries = toView.keySet(); - PDBEntry[] pdbs = pdbEntries.toArray(new PDBEntry[pdbEntries.size()]); - SequenceI[][] seqsForPdbs = new SequenceI[pdbEntries.size()][]; - for (int i = 0; i < pdbs.length; i++) - { - final List seqsForPdb = toView.get(pdbs[i]); - seqsForPdbs[i] = seqsForPdb.toArray(new SequenceI[seqsForPdb.size()]); - } - - openNewChimera(alignPanel, pdbs, seqsForPdbs); - } - - /** - * add a new structure (with associated sequences and chains) to this viewer, - * retrieving it if necessary first. - * - * @param pdbentry - * @param seq - * @param chains - * @param alignFrame - * @param align - * if true, new structure(s) will be align using associated alignment - */ - private void addStructure(final PDBEntry pdbentry, final SequenceI[] seq, - final String[] chains, final boolean b, - final IProgressIndicator alignFrame) - { - if (pdbentry.getFile() == null) - { - if (worker != null && worker.isAlive()) - { - // a retrieval is in progress, wait around and add ourselves to the - // queue. - new Thread(new Runnable() - { - public void run() - { - while (worker != null && worker.isAlive() && _started) - { - try - { - Thread.sleep(100 + ((int) Math.random() * 100)); - - } catch (Exception e) - { - } - - } - // and call ourselves again. - addStructure(pdbentry, seq, chains, b, alignFrame); - } - }).start(); - return; - } - } - // otherwise, start adding the structure. - jmb.addSequenceAndChain(new PDBEntry[] - { pdbentry }, new SequenceI[][] - { seq }, new String[][] - { chains }); - addingStructures = true; - _started = false; - alignAddedStructures = b; - // progressBar = alignFrame; // visual indication happens on caller frame. - (worker = new Thread(this)).start(); - return; - } - - private List getChimeraWindowsFor(AlignmentPanel apanel) - { - List result = new ArrayList(); - JInternalFrame[] frames = Desktop.instance.getAllFrames(); - - for (JInternalFrame frame : frames) - { - if (frame instanceof ChimeraViewFrame) - { - if (((StructureViewerBase) frame).isLinkedWith(apanel)) - { - result.add((ChimeraViewFrame) frame); - } - } - } - return result; + setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); } /** @@ -596,148 +320,53 @@ public class ChimeraViewFrame extends StructureViewerBase void initChimera() { jmb.setFinishedInit(false); - jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true), - getBounds().width, getBounds().height); - - jmb.launchChimera(); + Desktop.addInternalFrame(this, + jmb.getViewerTitle(getViewerName(), true), getBounds().width, + getBounds().height); + + if (!jmb.launchChimera()) + { + JvOptionPane.showMessageDialog(Desktop.desktop, + MessageManager.formatMessage("label.open_viewer_failed", + getViewerName()), + MessageManager.getString("label.error_loading_file"), + JvOptionPane.ERROR_MESSAGE); + jmb.closeViewer(true); + this.dispose(); + return; + } if (this.chimeraSessionFile != null) { boolean opened = jmb.openSession(chimeraSessionFile); if (!opened) { - System.err - .println("An error occurred opening Chimera session file " - + chimeraSessionFile); + System.err.println("An error occurred opening Chimera session file " + + chimeraSessionFile); } } - jmb.setFinishedInit(true); jmb.startChimeraListener(); } /** - * If the list is not empty, add menu items for 'All' and each individual - * chain to the "View | Show Chain" sub-menu. Multiple selections are allowed. - * - * @param chainNames - */ - void setChainMenuItems(List chainNames) - { - chainMenu.removeAll(); - if (chainNames == null || chainNames.isEmpty()) - { - return; - } - JMenuItem menuItem = new JMenuItem( - MessageManager.getString("label.all")); - menuItem.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent evt) - { - allChainsSelected = true; - for (int i = 0; i < chainMenu.getItemCount(); i++) - { - if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) - { - ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true); - } - } - showSelectedChains(); - allChainsSelected = false; - } - }); - - chainMenu.add(menuItem); - - for (String chainName : chainNames) - { - menuItem = new JCheckBoxMenuItem(chainName, true); - menuItem.addItemListener(new ItemListener() - { - public void itemStateChanged(ItemEvent evt) - { - if (!allChainsSelected) - { - showSelectedChains(); - } - } - }); - - chainMenu.add(menuItem); - } - } - - /** - * Show only the selected chain(s) in the viewer - */ - void showSelectedChains() - { - List toshow = new ArrayList(); - for (int i = 0; i < chainMenu.getItemCount(); i++) - { - if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) - { - JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i); - if (item.isSelected()) - { - toshow.add(item.getText()); - } - } - } - jmb.showChains(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. - * - * @param closeChimera - * if true, close any linked Chimera process; if false, prompt first - */ - public void closeViewer(boolean closeChimera) - { - 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(); - // TODO: check for memory leaks where instance isn't finalised because jmb - // holds a reference to the window - jmb = null; - } - - /** * Open any newly added PDB structures in Chimera, having first fetched data * from PDB (if not already saved). */ + @Override public void run() { _started = true; // 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 filePDB = new ArrayList<>(); + List filePDBpos = new ArrayList<>(); PDBEntry thePdbEntry = null; + StructureFile pdb = null; try { - String[] curfiles = jmb.getPdbFile(); // files currently in viewer + String[] curfiles = jmb.getStructureFiles(); // files currently in viewer // TODO: replace with reference fetching/transfer code (validate PDBentry // as a DBRef?) for (int pi = 0; pi < jmb.getPdbCount(); pi++) @@ -779,7 +408,7 @@ public class ChimeraViewFrame extends StructureViewerBase { filePDB.add(thePdbEntry); filePDBpos.add(Integer.valueOf(pi)); - files.append(" \"" + Platform.escapeString(file) + "\""); + files.append(" \"" + Platform.escapeBackslashes(file) + "\""); } } } catch (OutOfMemoryError oomerror) @@ -789,22 +418,23 @@ public class ChimeraViewFrame extends StructureViewerBase } catch (Exception ex) { ex.printStackTrace(); - errormsgs.append("When retrieving pdbfiles for '" - + thePdbEntry.getId() + "'"); + 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 Object[] - { errormsgs.toString() }), MessageManager - .getString("label.couldnt_load_file"), - JOptionPane.ERROR_MESSAGE); + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + MessageManager.formatMessage( + "label.pdb_entries_couldnt_be_retrieved", new Object[] + { errormsgs.toString() }), + MessageManager.getString("label.couldnt_load_file"), + JvOptionPane.ERROR_MESSAGE); } if (files.length() > 0) { + jmb.setFinishedInit(false); if (!addingStructures) { try @@ -812,9 +442,15 @@ public class ChimeraViewFrame extends StructureViewerBase initChimera(); } catch (Exception ex) { - Cache.log.error("Couldn't open Chimera viewer!", ex); + Console.error("Couldn't open Chimera viewer!", ex); } } + if (!jmb.isViewerRunning()) + { + // nothing to do + // TODO: ensure we tidy up JAL-3619 + return; + } int num = -1; for (PDBEntry pe : filePDB) { @@ -824,17 +460,18 @@ public class ChimeraViewFrame extends StructureViewerBase try { int pos = filePDBpos.get(num).intValue(); - long startTime = startProgressBar("Chimera " - + MessageManager.getString("status.opening_file")); + long startTime = startProgressBar(getViewerName() + " " + + MessageManager.getString("status.opening_file_for") + + " " + pe.getId()); jmb.openFile(pe); jmb.addSequence(pos, jmb.getSequence()[pos]); File fl = new File(pe.getFile()); - String protocol = AppletFormatAdapter.URL; + DataSourceType protocol = DataSourceType.URL; try { if (fl.exists()) { - protocol = AppletFormatAdapter.FILE; + protocol = DataSourceType.FILE; } } catch (Throwable e) { @@ -843,10 +480,12 @@ public class ChimeraViewFrame extends StructureViewerBase stopProgressBar("", startTime); } // Explicitly map to the filename used by Chimera ; - jmb.getSsm().setMapping(jmb.getSequence()[pos], - jmb.getChains()[pos], - pe.getFile(), - protocol); + + pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos], + jmb.getChains()[pos], pe.getFile(), protocol, + getProgressIndicator()); + jmb.stashFoundChains(pdb, pe.getFile()); + } catch (OutOfMemoryError oomerror) { new OOMWarning( @@ -854,19 +493,33 @@ public class ChimeraViewFrame extends StructureViewerBase oomerror); } catch (Exception ex) { - Cache.log.error("Couldn't open " + pe.getFile() - + " in Chimera viewer!", ex); + Console.error( + "Couldn't open " + pe.getFile() + " in Chimera viewer!", + ex); } finally { - Cache.log.debug("File locations are " + files); + Console.debug("File locations are " + files); } } } + + jmb.refreshGUI(); jmb.setFinishedInit(true); jmb.setLoadingFromArchive(false); + /* + * ensure that any newly discovered features (e.g. RESNUM) + * are notified to the FeatureRenderer (and added to any + * open feature settings dialog) + */ + FeatureRenderer fr = getBinding().getFeatureRenderer(null); + if (fr != null) + { + fr.featuresAdded(); + } + // refresh the sequence colours for the new structure(s) - for (AlignmentPanel ap : _colourwith) + for (AlignmentViewPanel ap : _colourwith) { jmb.updateColours(ap); } @@ -875,12 +528,12 @@ public class ChimeraViewFrame extends StructureViewerBase { new Thread(new Runnable() { + @Override public void run() { - alignStructs_withAllAlignPanels(); + alignStructsWithAllAlignPanels(); } }).start(); - alignAddedStructures = false; } addingStructures = false; } @@ -888,409 +541,11 @@ public class ChimeraViewFrame extends StructureViewerBase worker = null; } - /** - * Fetch PDB data and save to a local file. Returns the full path to the file, - * or null if fetch fails. - * - * @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 handle = System.currentTimeMillis() - + Thread.currentThread().hashCode(); - - /* - * Write 'fetching PDB' progress on AlignFrame as we are not yet visible - */ - String msg = MessageManager.formatMessage("status.fetching_pdb", - new Object[] - { pdbid }); - getAlignmentPanel().alignFrame.setProgressBar(msg, handle); - // long hdl = startProgressBar(MessageManager.formatMessage( - // "status.fetching_pdb", new Object[] - // { pdbid })); - try - { - pdbseq = pdbclient.getSequenceRecords(pdbid); - } catch (OutOfMemoryError oomerror) - { - new OOMWarning("Retrieving PDB id " + pdbid, oomerror); - } finally - { - msg = pdbid + " " - + MessageManager.getString("label.state_completed"); - getAlignmentPanel().alignFrame.setProgressBar(msg, handle); - // stopProgressBar(msg, hdl); - } - /* - * If PDB data were saved and are not invalid (empty alignment), return the - * file path. - */ - if (pdbseq != null && pdbseq.getHeight() > 0) - { - // just use the file name from the first sequence's first PDBEntry - filePath = new File(pdbseq.getSequenceAt(0).getPDBId() - .elementAt(0).getFile()).getAbsolutePath(); - processingEntry.setFile(filePath); - } - return filePath; - } - - /** - * Convenience method to update the progress bar if there is one. Be sure to - * call stopProgressBar with the returned handle to remove the message. - * - * @param msg - * @param handle - */ - public long startProgressBar(String msg) - { - // TODO would rather have startProgress/stopProgress as the - // IProgressIndicator interface - long tm = random.nextLong(); - if (progressBar != null) - { - progressBar.setProgressBar(msg, tm); - } - return tm; - } - - /** - * End the progress bar with the specified handle, leaving a message (if not - * null) on the status bar - * - * @param msg - * @param handle - */ - public void stopProgressBar(String msg, long handle) - { - if (progressBar != null) - { - progressBar.setProgressBar(msg, handle); - } - } - @Override - public void pdbFile_actionPerformed(ActionEvent actionEvent) + public void makePDBImage(TYPE imageType) { - JalviewFileChooser chooser = new JalviewFileChooser( - jalview.bin.Cache.getProperty("LAST_DIRECTORY")); - - chooser.setFileView(new JalviewFileView()); - 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 - in = new BufferedReader(new FileReader(jmb.getPdbFile()[0])); - File outFile = chooser.getSelectedFile(); - - PrintWriter out = new PrintWriter(new FileOutputStream(outFile)); - String data; - while ((data = in.readLine()) != null) - { - if (!(data.indexOf("
") > -1 || data.indexOf("
") > -1)) - { - out.println(data); - } - } - out.close(); - } 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 - { - cap.appendText(jmb.printMappings()); - } catch (OutOfMemoryError e) - { - new OOMWarning( - "composing sequence-structure alignments for display in text box.", - e); - cap.dispose(); - return; - } - jalview.gui.Desktop.addInternalFrame(cap, - MessageManager.getString("label.pdb_sequence_mapping"), 550, - 600); - } - - @Override - public void eps_actionPerformed(ActionEvent e) - { - throw new Error( - MessageManager - .getString("error.eps_generation_not_implemented")); - } - - @Override - public void png_actionPerformed(ActionEvent e) - { - throw new Error( - MessageManager - .getString("error.png_generation_not_implemented")); - } - - @Override - public void viewerColour_actionPerformed(ActionEvent actionEvent) - { - if (viewerColour.isSelected()) - { - // disable automatic sequence colouring. - jmb.setColourBySequence(false); - } - } - - @Override - public void seqColour_actionPerformed(ActionEvent actionEvent) - { - jmb.setColourBySequence(seqColour.isSelected()); - if (_colourwith == null) - { - _colourwith = new Vector(); - } - if (jmb.isColourBySequence()) - { - if (!jmb.isLoadingFromArchive()) - { - if (_colourwith.size() == 0 && getAlignmentPanel() != null) - { - // Make the currently displayed alignment panel the associated view - _colourwith.add(getAlignmentPanel().alignFrame.alignPanel); - } - } - // Set the colour using the current view for the associated alignframe - for (AlignmentPanel ap : _colourwith) - { - 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, MessageManager - .getString("label.select_backgroud_colour"), null); - if (col != null) - { - jmb.setBackgroundColour(col); - } - } - - @Override - public void showHelp_actionPerformed(ActionEvent actionEvent) - { - try - { - jalview.util.BrowserLauncher - .openURL("https://www.cgl.ucsf.edu/chimera/docs/UsersGuide"); - } catch (Exception ex) - { - } - } - - public void updateTitleAndMenus() - { - if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0) - { - repaint(); - return; - } - setChainMenuItems(jmb.getChainNames()); - - this.setTitle(jmb.getViewerTitle("Chimera", true)); - if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1) - { - viewerActionMenu.setVisible(true); - } - if (!jmb.isLoadingFromArchive()) - { - seqColour_actionPerformed(null); - } - } - - /* - * (non-Javadoc) - * - * @see - * jalview.jbgui.GStructureViewer#alignStructs_actionPerformed(java.awt.event - * .ActionEvent) - */ - @Override - protected void alignStructs_actionPerformed(ActionEvent actionEvent) - { - alignStructs_withAllAlignPanels(); - } - - private void alignStructs_withAllAlignPanels() - { - if (getAlignmentPanel() == null) - { - return; - } - - if (_alignwith.size() == 0) - { - _alignwith.add(getAlignmentPanel()); - } - - try - { - AlignmentI[] als = new Alignment[_alignwith.size()]; - ColumnSelection[] alc = new ColumnSelection[_alignwith.size()]; - int[] alm = new int[_alignwith.size()]; - int a = 0; - - for (AlignmentPanel ap : _alignwith) - { - als[a] = ap.av.getAlignment(); - alm[a] = -1; - alc[a++] = ap.av.getColumnSelection(); - } - jmb.superposeStructures(als, alm, alc); - } catch (Exception e) - { - StringBuffer sp = new StringBuffer(); - for (AlignmentPanel ap : _alignwith) - { - sp.append("'" + ap.alignFrame.getTitle() + "' "); - } - Cache.log.info("Couldn't align structures with the " + sp.toString() - + "associated alignment panels.", e); - } - } - - public void setJalviewColourScheme(ColourSchemeI ucs) - { - jmb.setJalviewColourScheme(ucs); - - } - - /** - * - * @param alignment - * @return first alignment panel displaying given alignment, or the default - * alignment panel - */ - public AlignmentPanel getAlignmentPanelFor(AlignmentI alignment) - { - for (AlignmentPanel ap : getAllAlignmentPanels()) - { - if (ap.av.getAlignment() == alignment) - { - return ap; - } - } - return getAlignmentPanel(); + throw new UnsupportedOperationException( + "Image export for Chimera is not implemented"); } @Override @@ -1299,37 +554,15 @@ public class ChimeraViewFrame extends StructureViewerBase return jmb; } - /** - * Ask Chimera to save its session to the designated file path. Returns true - * if successful, else false. - * - * @param filepath - * @see getStateInfo - */ - public boolean saveSession(String filepath) - { - boolean result = jmb.saveSession(filepath); - if (result) - { - this.chimeraSessionFile = filepath; - } - return result; - } - - /** - * 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() + public ViewerType getViewerType() { - return this.chimeraSessionFile == null ? "" : chimeraSessionFile; + return ViewerType.CHIMERA; } @Override - protected void fitToWindow_actionPerformed() + protected String getViewerName() { - jmb.focusView(); + return "Chimera"; } }