X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FStructureViewerBase.java;h=814623792a8c8e906a72a44777f449331007c74f;hb=17e77c3f2949a0729322b4a8d907f3f34b6a9914;hp=1feaa7ca05301bbe01e771f5e232e7c92a4bdb24;hpb=36933f9b768b9f8ace600215c1ddb4882331b92b;p=jalview.git diff --git a/src/jalview/gui/StructureViewerBase.java b/src/jalview/gui/StructureViewerBase.java index 1feaa7c..8146237 100644 --- a/src/jalview/gui/StructureViewerBase.java +++ b/src/jalview/gui/StructureViewerBase.java @@ -1,15 +1,41 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9) + * Copyright (C) 2015 The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ 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 @@ -26,18 +52,30 @@ public abstract class StructureViewerBase extends GStructureViewer * list of sequenceSet ids associated with the view */ protected List _aps = new ArrayList(); + /** * list of alignment panels to use for superposition */ protected Vector _alignwith = new Vector(); + /** * list of alignment panels that are used for colouring structures by aligned * sequences */ 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; + /** * * @param ap2 @@ -50,7 +88,7 @@ public abstract class StructureViewerBase extends GStructureViewer public boolean isUsedforaligment(AlignmentPanel ap2) { - + return (_alignwith != null) && _alignwith.contains(ap2); } @@ -128,7 +166,7 @@ public abstract class StructureViewerBase extends GStructureViewer list = t; } } - + return list; } @@ -199,7 +237,8 @@ public abstract class StructureViewerBase extends GStructureViewer } } - public void useAlignmentPanelForColourbyseq(AlignmentPanel nap, boolean enableColourBySeq) + public void useAlignmentPanelForColourbyseq(AlignmentPanel nap, + boolean enableColourBySeq) { useAlignmentPanelForColourbyseq(nap); getBinding().setColourBySequence(enableColourBySeq); @@ -225,4 +264,232 @@ 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; + } }