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 targetChainIds
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[] targetChainIds,
346 * There will be better ways of doing this in the future, for now we'll use
347 * the tried and tested MCview pdb mapping
349 boolean parseSecStr = processSecondaryStructure;
350 if (isPDBFileRegistered(pdbFile))
352 for (SequenceI sq : sequenceArray)
355 while (ds.getDatasetSequence() != null)
357 ds = ds.getDatasetSequence();
360 if (ds.getAnnotation() != null)
362 for (AlignmentAnnotation ala : ds.getAnnotation())
364 // false if any annotation present from this structure
365 // JBPNote this fails for jmol/chimera view because the *file* is
366 // passed, not the structure data ID -
367 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
376 boolean isMapUsingSIFTs = Boolean.valueOf(jalview.bin.Cache.getDefault(
377 "MAP_WITH_SIFTS", "false"));
378 SiftsClient siftsClient = null;
381 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
384 if (pdb.id != null && pdb.id.trim().length() > 0
385 && AppletFormatAdapter.FILE.equals(protocol))
387 registerPDBFile(pdb.id.trim(), pdbFile);
389 } catch (Exception ex)
391 ex.printStackTrace();
399 siftsClient = new SiftsClient(pdb);
401 } catch (SiftsException e)
403 isMapUsingSIFTs = false;
407 String targetChainId;
408 for (int s = 0; s < sequenceArray.length; s++)
410 boolean infChain = true;
411 final SequenceI seq = sequenceArray[s];
412 if (targetChainIds != null && targetChainIds[s] != null)
415 targetChainId = targetChainIds[s];
417 else if (seq.getName().indexOf("|") > -1)
419 targetChainId = seq.getName().substring(
420 seq.getName().lastIndexOf("|") + 1);
421 if (targetChainId.length() > 1)
423 if (targetChainId.trim().length() == 0)
429 // not a valid chain identifier
440 * Attempt pairwise alignment of the sequence with each chain in the PDB,
441 * and remember the highest scoring chain
444 AlignSeq maxAlignseq = null;
445 String maxChainId = " ";
446 PDBChain maxChain = null;
447 boolean first = true;
448 for (PDBChain chain : pdb.chains)
450 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
453 continue; // don't try to map chains don't match.
455 // TODO: correctly determine sequence type for mixed na/peptide
457 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
458 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
461 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
462 // as.calcScoreMatrix();
463 // as.traceAlignment();
465 if (first || as.maxscore > max
466 || (as.maxscore == max && chain.id.equals(targetChainId)))
472 maxChainId = chain.id;
475 if (maxChain == null)
480 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
482 pdbFile = "INLINE" + pdb.id;
485 ArrayList<StructureMapping> seqToStrucMapping = null;
490 jalview.datamodel.Mapping sqmpping = maxAlignseq
491 .getMappingFromS1(false);
492 seqToStrucMapping = new ArrayList<StructureMapping>();
493 if (targetChainId != null && !targetChainId.trim().isEmpty())
495 StructureMapping curChainMapping = siftsClient
496 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
497 seqToStrucMapping.add(curChainMapping);
498 maxChainId = targetChainId;
499 PDBChain chain = pdb.findChain(targetChainId);
502 chain.transferResidueAnnotation(curChainMapping, sqmpping);
507 for (PDBChain chain : pdb.chains)
509 StructureMapping curChainMapping = siftsClient
510 .getSiftsStructureMapping(seq, pdbFile, chain.id);
511 seqToStrucMapping.add(curChainMapping);
512 maxChainId = chain.id;
513 chain.transferResidueAnnotation(curChainMapping, sqmpping);
516 } catch (SiftsException e)
520 .println(">>>>>>> SIFTs mapping could not be obtained... Now mapping with NW alignment");
521 seqToStrucMapping = getNWMappings(seq, pdbFile, maxChainId,
522 maxChain, pdb, maxAlignseq);
527 seqToStrucMapping = getNWMappings(seq, pdbFile,
528 maxChainId, maxChain, pdb,
532 if (forStructureView)
534 // mappings.add(seqToStrucMapping);
535 mappings.addAll(seqToStrucMapping);
541 private ArrayList<StructureMapping> getNWMappings(SequenceI seq,
543 String maxChainId, PDBChain maxChain, PDBfile pdb,
544 AlignSeq maxAlignseq)
546 final StringBuilder mappingDetails = new StringBuilder(128);
547 mappingDetails.append(NEWLINE).append(
548 "Sequence \u27f7 Structure mapping details");
549 mappingDetails.append(NEWLINE);
551 .append("Method: inferred with Needleman & Wunsch alignment");
552 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
553 .append(NEWLINE).append("Sequence = ")
554 .append(maxChain.sequence.getSequenceAsString());
555 mappingDetails.append(NEWLINE).append("No of residues = ")
556 .append(maxChain.residues.size()).append(NEWLINE)
558 PrintStream ps = new PrintStream(System.out)
561 public void print(String x)
563 mappingDetails.append(x);
567 public void println()
569 mappingDetails.append(NEWLINE);
573 maxAlignseq.printAlignment(ps);
575 mappingDetails.append(NEWLINE).append("PDB start/end ");
576 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
578 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
579 mappingDetails.append(NEWLINE).append("SEQ start/end ");
580 mappingDetails.append(
581 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
583 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
584 + (seq.getStart() - 1)));
585 mappingDetails.append(NEWLINE);
586 maxChain.makeExactMapping(maxAlignseq, seq);
587 jalview.datamodel.Mapping sqmpping = maxAlignseq
588 .getMappingFromS1(false);
589 maxChain.transferRESNUMFeatures(seq, null);
591 // allocate enough slots to store the mapping from positions in
592 // sequence[s] to the associated chain
593 int[][] mapping = new int[seq.findPosition(seq.getLength()) + 2][2];
599 Atom tmp = maxChain.atoms.elementAt(index);
600 if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
602 resNum = tmp.resNumber;
603 if (tmp.alignmentMapping >= -1)
605 // TODO (JAL-1836) address root cause: negative residue no in PDB
607 mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber;
608 mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex;
613 } while (index < maxChain.atoms.size());
615 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
616 pdb.id, maxChainId, mapping, mappingDetails.toString());
617 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
618 ArrayList<StructureMapping> mappings = new ArrayList<StructureMapping>();
619 mappings.add(nwMapping);
623 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
625 listeners.removeElement(svl);
626 if (svl instanceof SequenceListener)
628 for (int i = 0; i < listeners.size(); i++)
630 if (listeners.elementAt(i) instanceof StructureListener)
632 ((StructureListener) listeners.elementAt(i))
633 .releaseReferences(svl);
638 if (pdbfiles == null)
644 * Remove mappings to the closed listener's PDB files, but first check if
645 * another listener is still interested
647 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
649 StructureListener sl;
650 for (int i = 0; i < listeners.size(); i++)
652 if (listeners.elementAt(i) instanceof StructureListener)
654 sl = (StructureListener) listeners.elementAt(i);
655 for (String pdbfile : sl.getPdbFile())
657 pdbs.remove(pdbfile);
663 * Rebuild the mappings set, retaining only those which are for 'other' PDB
668 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
669 for (StructureMapping sm : mappings)
671 if (!pdbs.contains(sm.pdbfile))
682 * Propagate mouseover of a single position in a structure
688 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
690 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
691 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
692 mouseOverStructure(atoms);
696 * Propagate mouseover or selection of multiple positions in a structure
700 public void mouseOverStructure(List<AtomSpec> atoms)
702 if (listeners == null)
704 // old or prematurely sent event
707 boolean hasSequenceListener = false;
708 for (int i = 0; i < listeners.size(); i++)
710 if (listeners.elementAt(i) instanceof SequenceListener)
712 hasSequenceListener = true;
715 if (!hasSequenceListener)
720 SearchResults results = new SearchResults();
721 for (AtomSpec atom : atoms)
723 SequenceI lastseq = null;
725 for (StructureMapping sm : mappings)
727 if (sm.pdbfile.equals(atom.getPdbFile())
728 && sm.pdbchain.equals(atom.getChain()))
730 int indexpos = sm.getSeqPos(atom.getPdbResNum());
731 if (lastipos != indexpos && lastseq != sm.sequence)
733 results.addResult(sm.sequence, indexpos, indexpos);
735 lastseq = sm.sequence;
736 // construct highlighted sequence list
737 for (AlignedCodonFrame acf : seqmappings)
739 acf.markMappedRegion(sm.sequence, indexpos, results);
745 for (Object li : listeners)
747 if (li instanceof SequenceListener)
749 ((SequenceListener) li).highlightSequence(results);
755 * highlight regions associated with a position (indexpos) in seq
758 * the sequence that the mouse over occurred on
760 * the absolute position being mouseovered in seq (0 to seq.length())
762 * the sequence position (if -1, seq.findPosition is called to
763 * resolve the residue number)
765 public void mouseOverSequence(SequenceI seq, int indexpos, int index,
768 boolean hasSequenceListeners = handlingVamsasMo
769 || !seqmappings.isEmpty();
770 SearchResults results = null;
773 index = seq.findPosition(indexpos);
775 for (int i = 0; i < listeners.size(); i++)
777 Object listener = listeners.elementAt(i);
778 if (listener == source)
780 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
781 // Temporary fudge with SequenceListener.getVamsasSource()
784 if (listener instanceof StructureListener)
786 highlightStructure((StructureListener) listener, seq, index);
790 if (listener instanceof SequenceListener)
792 final SequenceListener seqListener = (SequenceListener) listener;
793 if (hasSequenceListeners
794 && seqListener.getVamsasSource() != source)
796 if (relaySeqMappings)
800 results = MappingUtils.buildSearchResults(seq, index,
803 if (handlingVamsasMo)
805 results.addResult(seq, index, index);
808 if (!results.isEmpty())
810 seqListener.highlightSequence(results);
815 else if (listener instanceof VamsasListener && !handlingVamsasMo)
817 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
820 else if (listener instanceof SecondaryStructureListener)
822 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
830 * Send suitable messages to a StructureListener to highlight atoms
831 * corresponding to the given sequence position.
837 protected void highlightStructure(StructureListener sl, SequenceI seq,
840 if (!sl.isListeningFor(seq))
845 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
846 for (StructureMapping sm : mappings)
848 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence())
850 atomNo = sm.getAtomNum(index);
854 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
855 .getPDBResNum(index), atomNo));
859 sl.highlightAtoms(atoms);
863 * true if a mouse over event from an external (ie Vamsas) source is being
866 boolean handlingVamsasMo = false;
871 * as mouseOverSequence but only route event to SequenceListeners
875 * in an alignment sequence
877 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
880 handlingVamsasMo = true;
881 long msg = sequenceI.hashCode() * (1 + position);
885 mouseOverSequence(sequenceI, position, -1, source);
887 handlingVamsasMo = false;
890 public Annotation[] colourSequenceFromStructure(SequenceI seq,
894 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
895 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
897 * Annotation [] annotations = new Annotation[seq.getLength()];
899 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
900 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
901 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
903 * for (int j = 0; j < mappings.length; j++) {
905 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
906 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
907 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
908 * "+mappings[j].pdbfile);
910 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
911 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
913 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
914 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
915 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
916 * mappings[j].pdbfile); }
918 * annotations[index] = new Annotation("X",null,' ',0,col); } return
919 * annotations; } } } }
921 * return annotations;
925 public void structureSelectionChanged()
929 public void sequenceSelectionChanged()
933 public void sequenceColoursChanged(Object source)
935 StructureListener sl;
936 for (int i = 0; i < listeners.size(); i++)
938 if (listeners.elementAt(i) instanceof StructureListener)
940 sl = (StructureListener) listeners.elementAt(i);
941 sl.updateColours(source);
946 public StructureMapping[] getMapping(String pdbfile)
948 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
949 for (StructureMapping sm : mappings)
951 if (sm.pdbfile.equals(pdbfile))
956 return tmp.toArray(new StructureMapping[tmp.size()]);
960 * Returns a readable description of all mappings for the given pdbfile to any
961 * of the given sequences
967 public String printMappings(String pdbfile, List<SequenceI> seqs)
969 if (pdbfile == null || seqs == null || seqs.isEmpty())
974 StringBuilder sb = new StringBuilder(64);
975 for (StructureMapping sm : mappings)
977 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
979 sb.append(sm.mappingDetails);
981 // separator makes it easier to read multiple mappings
982 sb.append("=====================");
988 return sb.toString();
992 * Remove the given mapping
996 public void deregisterMapping(AlignedCodonFrame acf)
1000 boolean removed = seqmappings.remove(acf);
1001 if (removed && seqmappings.isEmpty())
1003 System.out.println("All mappings removed");
1009 * Add each of the given codonFrames to the stored set, if not aready present.
1013 public void registerMappings(Set<AlignedCodonFrame> set)
1017 for (AlignedCodonFrame acf : set)
1019 registerMapping(acf);
1025 * Add the given mapping to the stored set, unless already stored.
1027 public void registerMapping(AlignedCodonFrame acf)
1031 if (!seqmappings.contains(acf))
1033 seqmappings.add(acf);
1039 * Resets this object to its initial state by removing all registered
1040 * listeners, codon mappings, PDB file mappings
1042 public void resetAll()
1044 if (mappings != null)
1048 if (seqmappings != null)
1050 seqmappings.clear();
1052 if (sel_listeners != null)
1054 sel_listeners.clear();
1056 if (listeners != null)
1060 if (commandListeners != null)
1062 commandListeners.clear();
1064 if (view_listeners != null)
1066 view_listeners.clear();
1068 if (pdbFileNameId != null)
1070 pdbFileNameId.clear();
1072 if (pdbIdFileName != null)
1074 pdbIdFileName.clear();
1078 public void addSelectionListener(SelectionListener selecter)
1080 if (!sel_listeners.contains(selecter))
1082 sel_listeners.add(selecter);
1086 public void removeSelectionListener(SelectionListener toremove)
1088 if (sel_listeners.contains(toremove))
1090 sel_listeners.remove(toremove);
1094 public synchronized void sendSelection(
1095 jalview.datamodel.SequenceGroup selection,
1096 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1098 for (SelectionListener slis : sel_listeners)
1102 slis.selection(selection, colsel, source);
1107 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1109 public synchronized void sendViewPosition(
1110 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1111 int startSeq, int endSeq)
1114 if (view_listeners != null && view_listeners.size() > 0)
1116 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1118 while (listeners.hasMoreElements())
1120 AlignmentViewPanelListener slis = listeners.nextElement();
1123 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1131 * release all references associated with this manager provider
1133 * @param jalviewLite
1135 public static void release(StructureSelectionManagerProvider jalviewLite)
1137 // synchronized (instances)
1139 if (instances == null)
1143 StructureSelectionManager mnger = (instances.get(jalviewLite));
1146 instances.remove(jalviewLite);
1150 } catch (Throwable x)
1157 public void registerPDBEntry(PDBEntry pdbentry)
1159 if (pdbentry.getFile() != null
1160 && pdbentry.getFile().trim().length() > 0)
1162 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1166 public void addCommandListener(CommandListener cl)
1168 if (!commandListeners.contains(cl))
1170 commandListeners.add(cl);
1174 public boolean hasCommandListener(CommandListener cl)
1176 return this.commandListeners.contains(cl);
1179 public boolean removeCommandListener(CommandListener l)
1181 return commandListeners.remove(l);
1185 * Forward a command to any command listeners (except for the command's
1189 * the command to be broadcast (in its form after being performed)
1191 * if true, the command was being 'undone'
1194 public void commandPerformed(CommandI command, boolean undo,
1195 VamsasSource source)
1197 for (CommandListener listener : commandListeners)
1199 listener.mirrorCommand(command, undo, this, source);
1204 * Returns a new CommandI representing the given command as mapped to the
1205 * given sequences. If no mapping could be made, or the command is not of a
1206 * mappable kind, returns null.
1214 public CommandI mapCommand(CommandI command, boolean undo,
1215 final AlignmentI mapTo, char gapChar)
1217 if (command instanceof EditCommand)
1219 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1220 mapTo, gapChar, seqmappings);
1222 else if (command instanceof OrderCommand)
1224 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1225 mapTo, seqmappings);