2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.structure;
23 import jalview.analysis.AlignSeq;
24 import jalview.api.StructureSelectionManagerProvider;
25 import jalview.commands.CommandI;
26 import jalview.commands.EditCommand;
27 import jalview.commands.OrderCommand;
28 import jalview.datamodel.AlignedCodonFrame;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.Annotation;
32 import jalview.datamodel.PDBEntry;
33 import jalview.datamodel.SearchResults;
34 import jalview.datamodel.SequenceI;
35 import jalview.io.AppletFormatAdapter;
36 import jalview.util.MappingUtils;
37 import jalview.util.MessageManager;
38 import jalview.ws.sifts.SiftsClient;
39 import jalview.ws.sifts.SiftsException;
41 import java.io.PrintStream;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collections;
45 import java.util.Enumeration;
46 import java.util.HashMap;
47 import java.util.IdentityHashMap;
48 import java.util.LinkedHashSet;
49 import java.util.List;
52 import java.util.Vector;
55 import MCview.PDBChain;
56 import MCview.PDBfile;
58 public class StructureSelectionManager
60 public final static String NEWLINE = System.lineSeparator();
62 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
64 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
66 private boolean processSecondaryStructure = false;
68 private boolean secStructServices = false;
70 private boolean addTempFacAnnot = false;
73 * Set of any registered mappings between (dataset) sequences.
75 public Set<AlignedCodonFrame> seqmappings = new LinkedHashSet<AlignedCodonFrame>();
77 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
79 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
82 * @return true if will try to use external services for processing secondary
85 public boolean isSecStructServices()
87 return secStructServices;
91 * control use of external services for processing secondary structure
93 * @param secStructServices
95 public void setSecStructServices(boolean secStructServices)
97 this.secStructServices = secStructServices;
101 * flag controlling addition of any kind of structural annotation
103 * @return true if temperature factor annotation will be added
105 public boolean isAddTempFacAnnot()
107 return addTempFacAnnot;
111 * set flag controlling addition of structural annotation
113 * @param addTempFacAnnot
115 public void setAddTempFacAnnot(boolean addTempFacAnnot)
117 this.addTempFacAnnot = addTempFacAnnot;
122 * @return if true, the structure manager will attempt to add secondary
123 * structure lines for unannotated sequences
126 public boolean isProcessSecondaryStructure()
128 return processSecondaryStructure;
132 * Control whether structure manager will try to annotate mapped sequences
133 * with secondary structure from PDB data.
137 public void setProcessSecondaryStructure(boolean enable)
139 processSecondaryStructure = enable;
143 * debug function - write all mappings to stdout
145 public void reportMapping()
147 if (mappings.isEmpty())
149 System.err.println("reportMapping: No PDB/Sequence mappings.");
153 System.err.println("reportMapping: There are " + mappings.size()
156 for (StructureMapping sm : mappings)
158 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
164 * map between the PDB IDs (or structure identifiers) used by Jalview and the
165 * absolute filenames for PDB data that corresponds to it
167 Map<String, String> pdbIdFileName = new HashMap<String, String>();
169 Map<String, String> pdbFileNameId = new HashMap<String, String>();
171 public void registerPDBFile(String idForFile, String absoluteFile)
173 pdbIdFileName.put(idForFile, absoluteFile);
174 pdbFileNameId.put(absoluteFile, idForFile);
177 public String findIdForPDBFile(String idOrFile)
179 String id = pdbFileNameId.get(idOrFile);
183 public String findFileForPDBId(String idOrFile)
185 String id = pdbIdFileName.get(idOrFile);
189 public boolean isPDBFileRegistered(String idOrFile)
191 return pdbFileNameId.containsKey(idOrFile)
192 || pdbIdFileName.containsKey(idOrFile);
195 private static StructureSelectionManager nullProvider = null;
197 public static StructureSelectionManager getStructureSelectionManager(
198 StructureSelectionManagerProvider context)
202 if (nullProvider == null)
204 if (instances != null)
208 .getString("error.implementation_error_structure_selection_manager_null"),
209 new NullPointerException(MessageManager
210 .getString("exception.ssm_context_is_null")));
214 nullProvider = new StructureSelectionManager();
219 if (instances == null)
221 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
223 StructureSelectionManager instance = instances.get(context);
224 if (instance == null)
226 if (nullProvider != null)
228 instance = nullProvider;
232 instance = new StructureSelectionManager();
234 instances.put(context, instance);
240 * flag controlling whether SeqMappings are relayed from received sequence
241 * mouse over events to other sequences
243 boolean relaySeqMappings = true;
246 * Enable or disable relay of seqMapping events to other sequences. You might
247 * want to do this if there are many sequence mappings and the host computer
252 public void setRelaySeqMappings(boolean relay)
254 relaySeqMappings = relay;
258 * get the state of the relay seqMappings flag.
260 * @return true if sequence mouse overs are being relayed to other mapped
263 public boolean isRelaySeqMappingsEnabled()
265 return relaySeqMappings;
268 Vector listeners = new Vector();
271 * register a listener for alignment sequence mouseover events
275 public void addStructureViewerListener(Object svl)
277 if (!listeners.contains(svl))
279 listeners.addElement(svl);
284 * Returns the file name for a mapped PDB id (or null if not mapped).
289 public String alreadyMappedToFile(String pdbid)
291 for (StructureMapping sm : mappings)
293 if (sm.getPdbId().equals(pdbid))
302 * Import structure data and register a structure mapping for broadcasting
303 * colouring, mouseovers and selection events (convenience wrapper).
306 * - one or more sequences to be mapped to pdbFile
307 * @param targetChains
308 * - optional chain specification for mapping each sequence to pdb
309 * (may be nill, individual elements may be nill)
311 * - structure data resource
313 * - how to resolve data from resource
314 * @return null or the structure data parsed as a pdb file
316 synchronized public PDBfile setMapping(SequenceI[] sequence,
317 String[] targetChains, String pdbFile, String protocol)
319 return setMapping(true, sequence, targetChains, pdbFile, protocol);
323 * create sequence structure mappings between each sequence and the given
324 * pdbFile (retrieved via the given protocol).
326 * @param forStructureView
327 * when true, record the mapping for use in mouseOvers
329 * @param sequenceArray
330 * - one or more sequences to be mapped to pdbFile
331 * @param targetChains
332 * - optional chain specification for mapping each sequence to pdb
333 * (may be nill, individual elements may be nill)
335 * - structure data resource
337 * - how to resolve data from resource
338 * @return null or the structure data parsed as a pdb file
340 synchronized public PDBfile setMapping(boolean forStructureView,
341 SequenceI[] sequenceArray, String[] targetChains, String pdbFile,
345 * There will be better ways of doing this in the future, for now we'll use
346 * the tried and tested MCview pdb mapping
348 boolean parseSecStr = processSecondaryStructure;
349 if (isPDBFileRegistered(pdbFile))
351 for (SequenceI sq : sequenceArray)
354 while (ds.getDatasetSequence() != null)
356 ds = ds.getDatasetSequence();
359 if (ds.getAnnotation() != null)
361 for (AlignmentAnnotation ala : ds.getAnnotation())
363 // false if any annotation present from this structure
364 // JBPNote this fails for jmol/chimera view because the *file* is
365 // passed, not the structure data ID -
366 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
375 boolean isMapUsingSIFTs = Boolean.valueOf(jalview.bin.Cache.getDefault(
376 "MAP_WITH_SIFTS", "false"));
377 SiftsClient siftsClient = null;
380 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
384 siftsClient = new SiftsClient(pdb);
386 if (pdb.id != null && pdb.id.trim().length() > 0
387 && AppletFormatAdapter.FILE.equals(protocol))
389 registerPDBFile(pdb.id.trim(), pdbFile);
391 } catch (SiftsException e)
394 } catch (Exception ex)
396 ex.printStackTrace();
401 for (int s = 0; s < sequenceArray.length; s++)
403 boolean infChain = true;
404 final SequenceI seq = sequenceArray[s];
405 if (targetChains != null && targetChains[s] != null)
408 targetChain = targetChains[s];
410 else if (seq.getName().indexOf("|") > -1)
412 targetChain = seq.getName().substring(
413 seq.getName().lastIndexOf("|") + 1);
414 if (targetChain.length() > 1)
416 if (targetChain.trim().length() == 0)
422 // not a valid chain identifier
433 * Attempt pairwise alignment of the sequence with each chain in the PDB,
434 * and remember the highest scoring chain
437 AlignSeq maxAlignseq = null;
438 String maxChainId = " ";
439 PDBChain maxChain = null;
440 boolean first = true;
441 for (PDBChain chain : pdb.chains)
443 if (targetChain.length() > 0 && !targetChain.equals(chain.id)
446 continue; // don't try to map chains don't match.
448 // TODO: correctly determine sequence type for mixed na/peptide
450 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
451 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
454 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
455 // as.calcScoreMatrix();
456 // as.traceAlignment();
458 if (first || as.maxscore > max
459 || (as.maxscore == max && chain.id.equals(targetChain)))
465 maxChainId = chain.id;
468 if (maxChain == null)
473 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
475 pdbFile = "INLINE" + pdb.id;
478 ArrayList<StructureMapping> seqToStrucMapping = null;
483 seqToStrucMapping = new ArrayList<StructureMapping>();
484 if (targetChain != null && !targetChain.trim().isEmpty())
486 maxChainId = targetChain;
487 StructureMapping curChainMapping = siftsClient
488 .getSiftsStructureMapping(seq, pdbFile, targetChain);
489 seqToStrucMapping.add(curChainMapping);
493 for (PDBChain chain : pdb.chains)
495 maxChainId = chain.id;
496 StructureMapping curChainMapping = siftsClient
497 .getSiftsStructureMapping(seq, pdbFile, chain.id);
498 seqToStrucMapping.add(curChainMapping);
501 } catch (SiftsException e)
504 .println(">>>>>>> SIFTs mapping could not be obtained... Now mapping with NW alignment");
505 seqToStrucMapping = getNWMappings(seq, pdbFile, maxChainId,
506 maxChain, pdb, maxAlignseq);
511 seqToStrucMapping = getNWMappings(seq, pdbFile,
512 maxChainId, maxChain, pdb,
516 if (forStructureView)
518 // mappings.add(seqToStrucMapping);
519 mappings.addAll(seqToStrucMapping);
525 private ArrayList<StructureMapping> getNWMappings(SequenceI seq,
527 String maxChainId, PDBChain maxChain, PDBfile pdb,
528 AlignSeq maxAlignseq)
530 final StringBuilder mappingDetails = new StringBuilder(128);
531 mappingDetails.append(NEWLINE).append(
532 "Sequence \u27f7 Structure mapping details");
533 mappingDetails.append(NEWLINE);
535 .append("Method: inferred with Needleman & Wunsch alignment");
536 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
537 .append(NEWLINE).append("Sequence = ")
538 .append(maxChain.sequence.getSequenceAsString());
539 mappingDetails.append(NEWLINE).append("No of residues = ")
540 .append(maxChain.residues.size()).append(NEWLINE)
542 PrintStream ps = new PrintStream(System.out)
545 public void print(String x)
547 mappingDetails.append(x);
551 public void println()
553 mappingDetails.append(NEWLINE);
557 maxAlignseq.printAlignment(ps);
559 mappingDetails.append(NEWLINE).append("PDB start/end ");
560 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
562 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
563 mappingDetails.append(NEWLINE).append("SEQ start/end ");
564 mappingDetails.append(
565 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
567 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
568 + (seq.getStart() - 1)));
569 mappingDetails.append(NEWLINE);
570 maxChain.makeExactMapping(maxAlignseq, seq);
571 jalview.datamodel.Mapping sqmpping = maxAlignseq
572 .getMappingFromS1(false);
573 maxChain.transferRESNUMFeatures(seq, null);
575 // allocate enough slots to store the mapping from positions in
576 // sequence[s] to the associated chain
577 int[][] mapping = new int[seq.findPosition(seq.getLength()) + 2][2];
583 Atom tmp = maxChain.atoms.elementAt(index);
584 if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
586 resNum = tmp.resNumber;
587 if (tmp.alignmentMapping >= -1)
589 // TODO (JAL-1836) address root cause: negative residue no in PDB
591 mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber;
592 mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex;
597 } while (index < maxChain.atoms.size());
599 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
600 pdb.id, maxChainId, mapping, mappingDetails.toString());
601 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
602 ArrayList<StructureMapping> mappings = new ArrayList<StructureMapping>();
603 mappings.add(nwMapping);
607 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
609 listeners.removeElement(svl);
610 if (svl instanceof SequenceListener)
612 for (int i = 0; i < listeners.size(); i++)
614 if (listeners.elementAt(i) instanceof StructureListener)
616 ((StructureListener) listeners.elementAt(i))
617 .releaseReferences(svl);
622 if (pdbfiles == null)
628 * Remove mappings to the closed listener's PDB files, but first check if
629 * another listener is still interested
631 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
633 StructureListener sl;
634 for (int i = 0; i < listeners.size(); i++)
636 if (listeners.elementAt(i) instanceof StructureListener)
638 sl = (StructureListener) listeners.elementAt(i);
639 for (String pdbfile : sl.getPdbFile())
641 pdbs.remove(pdbfile);
647 * Rebuild the mappings set, retaining only those which are for 'other' PDB
652 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
653 for (StructureMapping sm : mappings)
655 if (!pdbs.contains(sm.pdbfile))
666 * Propagate mouseover of a single position in a structure
672 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
674 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
675 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
676 mouseOverStructure(atoms);
680 * Propagate mouseover or selection of multiple positions in a structure
684 public void mouseOverStructure(List<AtomSpec> atoms)
686 if (listeners == null)
688 // old or prematurely sent event
691 boolean hasSequenceListener = false;
692 for (int i = 0; i < listeners.size(); i++)
694 if (listeners.elementAt(i) instanceof SequenceListener)
696 hasSequenceListener = true;
699 if (!hasSequenceListener)
704 SearchResults results = new SearchResults();
705 for (AtomSpec atom : atoms)
707 SequenceI lastseq = null;
709 for (StructureMapping sm : mappings)
711 if (sm.pdbfile.equals(atom.getPdbFile())
712 && sm.pdbchain.equals(atom.getChain()))
714 int indexpos = sm.getSeqPos(atom.getPdbResNum());
715 if (lastipos != indexpos && lastseq != sm.sequence)
717 results.addResult(sm.sequence, indexpos, indexpos);
719 lastseq = sm.sequence;
720 // construct highlighted sequence list
721 for (AlignedCodonFrame acf : seqmappings)
723 acf.markMappedRegion(sm.sequence, indexpos, results);
729 for (Object li : listeners)
731 if (li instanceof SequenceListener)
733 ((SequenceListener) li).highlightSequence(results);
739 * highlight regions associated with a position (indexpos) in seq
742 * the sequence that the mouse over occurred on
744 * the absolute position being mouseovered in seq (0 to seq.length())
746 * the sequence position (if -1, seq.findPosition is called to
747 * resolve the residue number)
749 public void mouseOverSequence(SequenceI seq, int indexpos, int index,
752 boolean hasSequenceListeners = handlingVamsasMo
753 || !seqmappings.isEmpty();
754 SearchResults results = null;
757 index = seq.findPosition(indexpos);
759 for (int i = 0; i < listeners.size(); i++)
761 Object listener = listeners.elementAt(i);
762 if (listener == source)
764 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
765 // Temporary fudge with SequenceListener.getVamsasSource()
768 if (listener instanceof StructureListener)
770 highlightStructure((StructureListener) listener, seq, index);
774 if (listener instanceof SequenceListener)
776 final SequenceListener seqListener = (SequenceListener) listener;
777 if (hasSequenceListeners
778 && seqListener.getVamsasSource() != source)
780 if (relaySeqMappings)
784 results = MappingUtils.buildSearchResults(seq, index,
787 if (handlingVamsasMo)
789 results.addResult(seq, index, index);
792 if (!results.isEmpty())
794 seqListener.highlightSequence(results);
799 else if (listener instanceof VamsasListener && !handlingVamsasMo)
801 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
804 else if (listener instanceof SecondaryStructureListener)
806 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
814 * Send suitable messages to a StructureListener to highlight atoms
815 * corresponding to the given sequence position.
821 protected void highlightStructure(StructureListener sl, SequenceI seq,
824 if (!sl.isListeningFor(seq))
829 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
830 for (StructureMapping sm : mappings)
832 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence())
834 atomNo = sm.getAtomNum(index);
838 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
839 .getPDBResNum(index), atomNo));
843 sl.highlightAtoms(atoms);
847 * true if a mouse over event from an external (ie Vamsas) source is being
850 boolean handlingVamsasMo = false;
855 * as mouseOverSequence but only route event to SequenceListeners
859 * in an alignment sequence
861 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
864 handlingVamsasMo = true;
865 long msg = sequenceI.hashCode() * (1 + position);
869 mouseOverSequence(sequenceI, position, -1, source);
871 handlingVamsasMo = false;
874 public Annotation[] colourSequenceFromStructure(SequenceI seq,
878 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
879 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
881 * Annotation [] annotations = new Annotation[seq.getLength()];
883 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
884 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
885 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
887 * for (int j = 0; j < mappings.length; j++) {
889 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
890 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
891 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
892 * "+mappings[j].pdbfile);
894 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
895 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
897 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
898 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
899 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
900 * mappings[j].pdbfile); }
902 * annotations[index] = new Annotation("X",null,' ',0,col); } return
903 * annotations; } } } }
905 * return annotations;
909 public void structureSelectionChanged()
913 public void sequenceSelectionChanged()
917 public void sequenceColoursChanged(Object source)
919 StructureListener sl;
920 for (int i = 0; i < listeners.size(); i++)
922 if (listeners.elementAt(i) instanceof StructureListener)
924 sl = (StructureListener) listeners.elementAt(i);
925 sl.updateColours(source);
930 public StructureMapping[] getMapping(String pdbfile)
932 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
933 for (StructureMapping sm : mappings)
935 if (sm.pdbfile.equals(pdbfile))
940 return tmp.toArray(new StructureMapping[tmp.size()]);
944 * Returns a readable description of all mappings for the given pdbfile to any
945 * of the given sequences
951 public String printMappings(String pdbfile, List<SequenceI> seqs)
953 if (pdbfile == null || seqs == null || seqs.isEmpty())
958 StringBuilder sb = new StringBuilder(64);
959 for (StructureMapping sm : mappings)
961 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
963 sb.append(sm.mappingDetails);
965 // separator makes it easier to read multiple mappings
966 sb.append("=====================");
972 return sb.toString();
976 * Remove the given mapping
980 public void deregisterMapping(AlignedCodonFrame acf)
984 boolean removed = seqmappings.remove(acf);
985 if (removed && seqmappings.isEmpty())
987 System.out.println("All mappings removed");
993 * Add each of the given codonFrames to the stored set, if not aready present.
997 public void registerMappings(Set<AlignedCodonFrame> set)
1001 for (AlignedCodonFrame acf : set)
1003 registerMapping(acf);
1009 * Add the given mapping to the stored set, unless already stored.
1011 public void registerMapping(AlignedCodonFrame acf)
1015 if (!seqmappings.contains(acf))
1017 seqmappings.add(acf);
1023 * Resets this object to its initial state by removing all registered
1024 * listeners, codon mappings, PDB file mappings
1026 public void resetAll()
1028 if (mappings != null)
1032 if (seqmappings != null)
1034 seqmappings.clear();
1036 if (sel_listeners != null)
1038 sel_listeners.clear();
1040 if (listeners != null)
1044 if (commandListeners != null)
1046 commandListeners.clear();
1048 if (view_listeners != null)
1050 view_listeners.clear();
1052 if (pdbFileNameId != null)
1054 pdbFileNameId.clear();
1056 if (pdbIdFileName != null)
1058 pdbIdFileName.clear();
1062 public void addSelectionListener(SelectionListener selecter)
1064 if (!sel_listeners.contains(selecter))
1066 sel_listeners.add(selecter);
1070 public void removeSelectionListener(SelectionListener toremove)
1072 if (sel_listeners.contains(toremove))
1074 sel_listeners.remove(toremove);
1078 public synchronized void sendSelection(
1079 jalview.datamodel.SequenceGroup selection,
1080 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1082 for (SelectionListener slis : sel_listeners)
1086 slis.selection(selection, colsel, source);
1091 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1093 public synchronized void sendViewPosition(
1094 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1095 int startSeq, int endSeq)
1098 if (view_listeners != null && view_listeners.size() > 0)
1100 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1102 while (listeners.hasMoreElements())
1104 AlignmentViewPanelListener slis = listeners.nextElement();
1107 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1115 * release all references associated with this manager provider
1117 * @param jalviewLite
1119 public static void release(StructureSelectionManagerProvider jalviewLite)
1121 // synchronized (instances)
1123 if (instances == null)
1127 StructureSelectionManager mnger = (instances.get(jalviewLite));
1130 instances.remove(jalviewLite);
1134 } catch (Throwable x)
1141 public void registerPDBEntry(PDBEntry pdbentry)
1143 if (pdbentry.getFile() != null
1144 && pdbentry.getFile().trim().length() > 0)
1146 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1150 public void addCommandListener(CommandListener cl)
1152 if (!commandListeners.contains(cl))
1154 commandListeners.add(cl);
1158 public boolean hasCommandListener(CommandListener cl)
1160 return this.commandListeners.contains(cl);
1163 public boolean removeCommandListener(CommandListener l)
1165 return commandListeners.remove(l);
1169 * Forward a command to any command listeners (except for the command's
1173 * the command to be broadcast (in its form after being performed)
1175 * if true, the command was being 'undone'
1178 public void commandPerformed(CommandI command, boolean undo,
1179 VamsasSource source)
1181 for (CommandListener listener : commandListeners)
1183 listener.mirrorCommand(command, undo, this, source);
1188 * Returns a new CommandI representing the given command as mapped to the
1189 * given sequences. If no mapping could be made, or the command is not of a
1190 * mappable kind, returns null.
1198 public CommandI mapCommand(CommandI command, boolean undo,
1199 final AlignmentI mapTo, char gapChar)
1201 if (command instanceof EditCommand)
1203 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1204 mapTo, gapChar, seqmappings);
1206 else if (command instanceof OrderCommand)
1208 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1209 mapTo, seqmappings);