X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FStructureViewerBase.java;fp=src%2Fjalview%2Fgui%2FStructureViewerBase.java;h=587e08aa54a49623490ae42780aa5e3cfadc4764;hb=f06554784411ddbf871d642e66c8dcb7f147d4a8;hp=1feaa7ca05301bbe01e771f5e232e7c92a4bdb24;hpb=cf06ee5d732af6cc874115aece1138adafca8ad7;p=jalview.git diff --git a/src/jalview/gui/StructureViewerBase.java b/src/jalview/gui/StructureViewerBase.java index 1feaa7c..587e08a 100644 --- a/src/jalview/gui/StructureViewerBase.java +++ b/src/jalview/gui/StructureViewerBase.java @@ -1,15 +1,21 @@ package jalview.gui; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.gui.StructureViewer.ViewerType; +import jalview.gui.ViewSelectionMenu.ViewSetProvider; +import jalview.io.AppletFormatAdapter; +import jalview.jbgui.GStructureViewer; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.MessageManager; + import java.awt.Component; import java.util.ArrayList; import java.util.List; import java.util.Vector; import javax.swing.JMenuItem; - -import jalview.gui.StructureViewer.ViewerType; -import jalview.gui.ViewSelectionMenu.ViewSetProvider; -import jalview.jbgui.GStructureViewer; +import javax.swing.JOptionPane; /** * Base class with common functionality for JMol, Chimera or other structure @@ -37,6 +43,10 @@ public abstract class StructureViewerBase extends GStructureViewer protected Vector _colourwith = new Vector(); private String viewId = null; private AlignmentPanel ap; + protected boolean alignAddedStructures = false; + protected boolean _started = false; + protected boolean addingStructures = false; + protected Thread worker = null; /** * @@ -225,4 +235,227 @@ public abstract class StructureViewerBase extends GStructureViewer } public abstract ViewerType getViewerType(); + + protected abstract AAStructureBindingModel getBindingModel(); + + /** + * add a new structure (with associated sequences and chains) to this viewer, + * retrieving it if necessary first. + * + * @param pdbentry + * @param seqs + * @param chains + * @param align + * if true, new structure(s) will be aligned using associated + * alignment + * @param alignFrame + */ + protected void addStructure(final PDBEntry pdbentry, final SequenceI[] seqs, final String[] chains, + final boolean align, 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, seqs, chains, align, alignFrame); + } + }).start(); + return; + } + } + // otherwise, start adding the structure. + getBindingModel().addSequenceAndChain(new PDBEntry[] { pdbentry }, + new SequenceI[][] { seqs }, new String[][] { chains }); + addingStructures = true; + _started = false; + alignAddedStructures = align; + worker = new Thread(this); + worker.start(); + return; + } + + /** + * Presents a dialog with the option to add an align a structure to an + * existing structure view + * + * @param pdbId + * @param view + * @return YES, NO or CANCEL JOptionPane code + */ + protected int chooseAlignStructureToViewer(String pdbId, StructureViewerBase 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; + } + + protected abstract boolean hasPdbId(String pdbId); + + protected abstract List getViewersFor( + AlignmentPanel alp); + + /** + * Check for any existing views involving this alignment and give user the + * option to add and align this molecule to one of them + * + * @param pdbentry + * @param seq + * @param chains + * @param apanel + * @param pdbId + * @return true if user adds to a view, or cancels entirely, else false + */ + protected boolean addToExistingViewer(PDBEntry pdbentry, SequenceI[] seq, + String[] chains, final AlignmentPanel apanel, String pdbId) + { + for (StructureViewerBase view : getViewersFor(apanel)) + { + // TODO: highlight the 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 true; + } + else if (option == JOptionPane.YES_OPTION) + { + view.useAlignmentPanelForSuperposition(apanel); + view.addStructure(pdbentry, seq, chains, true, apanel.alignFrame); + return true; + } + else + { + // NO_OPTION - offer the next viewer if any + } + } + + /* + * nothing offered and selected + */ + return false; + } + + /** + * Adds mappings for the given sequences to an already opened PDB structure, + * and updates any viewers that have the PDB file + * + * @param seq + * @param chains + * @param apanel + * @param pdbFilename + */ + protected void addSequenceMappingsToStructure(SequenceI[] seq, + String[] chains, final AlignmentPanel apanel, String pdbFilename) + { + // TODO : Fix multiple seq to one chain issue here. + /* + * create the mappings + */ + apanel.getStructureSelectionManager().setMapping(seq, chains, pdbFilename, + AppletFormatAdapter.FILE); + + /* + * alert the FeatureRenderer to show new (PDB RESNUM) features + */ + if (apanel.getSeqPanel().seqCanvas.fr != null) + { + apanel.getSeqPanel().seqCanvas.fr.featuresAdded(); + apanel.paintAlignment(true); + } + + /* + * add the sequences to any other viewers (of the same type) for this pdb + * file + */ + // JBPNOTE: this looks like a binding routine, rather than a gui routine + for (StructureViewerBase viewer : getViewersFor(null)) + { + AAStructureBindingModel bindingModel = viewer.getBindingModel(); + for (int pe = 0; pe < bindingModel.getPdbCount(); pe++) + { + if (bindingModel.getPdbEntry(pe).getFile().equals(pdbFilename)) + { + bindingModel.addSequence(pe, seq); + viewer.addAlignmentPanel(apanel); + /* + * add it to the set of alignments used for colouring structure by + * sequence + */ + viewer.useAlignmentPanelForColourbyseq(apanel); + viewer.buildActionMenu(); + apanel.getStructureSelectionManager().sequenceColoursChanged(apanel); + break; + } + } + } + } + + /** + * Check if the PDB file is already loaded, if so offer to add it to the + * existing viewer + * + * @param seq + * @param chains + * @param apanel + * @param pdbId + * @return true if the user chooses to add to a viewer, or to cancel entirely + */ + protected boolean addAlreadyLoadedFile(SequenceI[] seq, String[] chains, + final AlignmentPanel apanel, String pdbId) + { + boolean finished = false; + String alreadyMapped = apanel.getStructureSelectionManager() + .alreadyMappedToFile(pdbId); + + if (alreadyMapped != null) + { + /* + * the PDB file is already loaded + */ + 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); + if (option == JOptionPane.CANCEL_OPTION) + { + finished = true; + } + else if (option == JOptionPane.YES_OPTION) + { + addSequenceMappingsToStructure(seq, chains, apanel, alreadyMapped); + finished = true; + } + } + return finished; + } }