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 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
597 Atom tmp = maxChain.atoms.elementAt(index);
598 if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
600 resNum = tmp.resNumber;
601 if (tmp.alignmentMapping >= -1)
603 // TODO (JAL-1836) address root cause: negative residue no in PDB
605 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
611 } while (index < maxChain.atoms.size());
613 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
614 pdb.id, maxChainId, mapping, mappingDetails.toString());
615 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
616 ArrayList<StructureMapping> mappings = new ArrayList<StructureMapping>();
617 mappings.add(nwMapping);
621 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
623 listeners.removeElement(svl);
624 if (svl instanceof SequenceListener)
626 for (int i = 0; i < listeners.size(); i++)
628 if (listeners.elementAt(i) instanceof StructureListener)
630 ((StructureListener) listeners.elementAt(i))
631 .releaseReferences(svl);
636 if (pdbfiles == null)
642 * Remove mappings to the closed listener's PDB files, but first check if
643 * another listener is still interested
645 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
647 StructureListener sl;
648 for (int i = 0; i < listeners.size(); i++)
650 if (listeners.elementAt(i) instanceof StructureListener)
652 sl = (StructureListener) listeners.elementAt(i);
653 for (String pdbfile : sl.getPdbFile())
655 pdbs.remove(pdbfile);
661 * Rebuild the mappings set, retaining only those which are for 'other' PDB
666 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
667 for (StructureMapping sm : mappings)
669 if (!pdbs.contains(sm.pdbfile))
680 * Propagate mouseover of a single position in a structure
686 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
688 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
689 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
690 mouseOverStructure(atoms);
694 * Propagate mouseover or selection of multiple positions in a structure
698 public void mouseOverStructure(List<AtomSpec> atoms)
700 if (listeners == null)
702 // old or prematurely sent event
705 boolean hasSequenceListener = false;
706 for (int i = 0; i < listeners.size(); i++)
708 if (listeners.elementAt(i) instanceof SequenceListener)
710 hasSequenceListener = true;
713 if (!hasSequenceListener)
718 SearchResults results = new SearchResults();
719 for (AtomSpec atom : atoms)
721 SequenceI lastseq = null;
723 for (StructureMapping sm : mappings)
725 if (sm.pdbfile.equals(atom.getPdbFile())
726 && sm.pdbchain.equals(atom.getChain()))
728 int indexpos = sm.getSeqPos(atom.getPdbResNum());
729 if (lastipos != indexpos && lastseq != sm.sequence)
731 results.addResult(sm.sequence, indexpos, indexpos);
733 lastseq = sm.sequence;
734 // construct highlighted sequence list
735 for (AlignedCodonFrame acf : seqmappings)
737 acf.markMappedRegion(sm.sequence, indexpos, results);
743 for (Object li : listeners)
745 if (li instanceof SequenceListener)
747 ((SequenceListener) li).highlightSequence(results);
753 * highlight regions associated with a position (indexpos) in seq
756 * the sequence that the mouse over occurred on
758 * the absolute position being mouseovered in seq (0 to seq.length())
760 * the sequence position (if -1, seq.findPosition is called to
761 * resolve the residue number)
763 public void mouseOverSequence(SequenceI seq, int indexpos, int index,
766 boolean hasSequenceListeners = handlingVamsasMo
767 || !seqmappings.isEmpty();
768 SearchResults results = null;
771 index = seq.findPosition(indexpos);
773 for (int i = 0; i < listeners.size(); i++)
775 Object listener = listeners.elementAt(i);
776 if (listener == source)
778 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
779 // Temporary fudge with SequenceListener.getVamsasSource()
782 if (listener instanceof StructureListener)
784 highlightStructure((StructureListener) listener, seq, index);
788 if (listener instanceof SequenceListener)
790 final SequenceListener seqListener = (SequenceListener) listener;
791 if (hasSequenceListeners
792 && seqListener.getVamsasSource() != source)
794 if (relaySeqMappings)
798 results = MappingUtils.buildSearchResults(seq, index,
801 if (handlingVamsasMo)
803 results.addResult(seq, index, index);
806 if (!results.isEmpty())
808 seqListener.highlightSequence(results);
813 else if (listener instanceof VamsasListener && !handlingVamsasMo)
815 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
818 else if (listener instanceof SecondaryStructureListener)
820 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
828 * Send suitable messages to a StructureListener to highlight atoms
829 * corresponding to the given sequence position.
835 protected void highlightStructure(StructureListener sl, SequenceI seq,
838 if (!sl.isListeningFor(seq))
843 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
844 for (StructureMapping sm : mappings)
846 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence())
848 atomNo = sm.getAtomNum(index);
852 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
853 .getPDBResNum(index), atomNo));
857 sl.highlightAtoms(atoms);
861 * true if a mouse over event from an external (ie Vamsas) source is being
864 boolean handlingVamsasMo = false;
869 * as mouseOverSequence but only route event to SequenceListeners
873 * in an alignment sequence
875 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
878 handlingVamsasMo = true;
879 long msg = sequenceI.hashCode() * (1 + position);
883 mouseOverSequence(sequenceI, position, -1, source);
885 handlingVamsasMo = false;
888 public Annotation[] colourSequenceFromStructure(SequenceI seq,
892 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
893 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
895 * Annotation [] annotations = new Annotation[seq.getLength()];
897 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
898 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
899 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
901 * for (int j = 0; j < mappings.length; j++) {
903 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
904 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
905 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
906 * "+mappings[j].pdbfile);
908 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
909 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
911 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
912 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
913 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
914 * mappings[j].pdbfile); }
916 * annotations[index] = new Annotation("X",null,' ',0,col); } return
917 * annotations; } } } }
919 * return annotations;
923 public void structureSelectionChanged()
927 public void sequenceSelectionChanged()
931 public void sequenceColoursChanged(Object source)
933 StructureListener sl;
934 for (int i = 0; i < listeners.size(); i++)
936 if (listeners.elementAt(i) instanceof StructureListener)
938 sl = (StructureListener) listeners.elementAt(i);
939 sl.updateColours(source);
944 public StructureMapping[] getMapping(String pdbfile)
946 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
947 for (StructureMapping sm : mappings)
949 if (sm.pdbfile.equals(pdbfile))
954 return tmp.toArray(new StructureMapping[tmp.size()]);
958 * Returns a readable description of all mappings for the given pdbfile to any
959 * of the given sequences
965 public String printMappings(String pdbfile, List<SequenceI> seqs)
967 if (pdbfile == null || seqs == null || seqs.isEmpty())
972 StringBuilder sb = new StringBuilder(64);
973 for (StructureMapping sm : mappings)
975 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
977 sb.append(sm.mappingDetails);
979 // separator makes it easier to read multiple mappings
980 sb.append("=====================");
986 return sb.toString();
990 * Remove the given mapping
994 public void deregisterMapping(AlignedCodonFrame acf)
998 boolean removed = seqmappings.remove(acf);
999 if (removed && seqmappings.isEmpty())
1001 System.out.println("All mappings removed");
1007 * Add each of the given codonFrames to the stored set, if not aready present.
1011 public void registerMappings(Set<AlignedCodonFrame> set)
1015 for (AlignedCodonFrame acf : set)
1017 registerMapping(acf);
1023 * Add the given mapping to the stored set, unless already stored.
1025 public void registerMapping(AlignedCodonFrame acf)
1029 if (!seqmappings.contains(acf))
1031 seqmappings.add(acf);
1037 * Resets this object to its initial state by removing all registered
1038 * listeners, codon mappings, PDB file mappings
1040 public void resetAll()
1042 if (mappings != null)
1046 if (seqmappings != null)
1048 seqmappings.clear();
1050 if (sel_listeners != null)
1052 sel_listeners.clear();
1054 if (listeners != null)
1058 if (commandListeners != null)
1060 commandListeners.clear();
1062 if (view_listeners != null)
1064 view_listeners.clear();
1066 if (pdbFileNameId != null)
1068 pdbFileNameId.clear();
1070 if (pdbIdFileName != null)
1072 pdbIdFileName.clear();
1076 public void addSelectionListener(SelectionListener selecter)
1078 if (!sel_listeners.contains(selecter))
1080 sel_listeners.add(selecter);
1084 public void removeSelectionListener(SelectionListener toremove)
1086 if (sel_listeners.contains(toremove))
1088 sel_listeners.remove(toremove);
1092 public synchronized void sendSelection(
1093 jalview.datamodel.SequenceGroup selection,
1094 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1096 for (SelectionListener slis : sel_listeners)
1100 slis.selection(selection, colsel, source);
1105 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1107 public synchronized void sendViewPosition(
1108 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1109 int startSeq, int endSeq)
1112 if (view_listeners != null && view_listeners.size() > 0)
1114 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1116 while (listeners.hasMoreElements())
1118 AlignmentViewPanelListener slis = listeners.nextElement();
1121 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1129 * release all references associated with this manager provider
1131 * @param jalviewLite
1133 public static void release(StructureSelectionManagerProvider jalviewLite)
1135 // synchronized (instances)
1137 if (instances == null)
1141 StructureSelectionManager mnger = (instances.get(jalviewLite));
1144 instances.remove(jalviewLite);
1148 } catch (Throwable x)
1155 public void registerPDBEntry(PDBEntry pdbentry)
1157 if (pdbentry.getFile() != null
1158 && pdbentry.getFile().trim().length() > 0)
1160 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1164 public void addCommandListener(CommandListener cl)
1166 if (!commandListeners.contains(cl))
1168 commandListeners.add(cl);
1172 public boolean hasCommandListener(CommandListener cl)
1174 return this.commandListeners.contains(cl);
1177 public boolean removeCommandListener(CommandListener l)
1179 return commandListeners.remove(l);
1183 * Forward a command to any command listeners (except for the command's
1187 * the command to be broadcast (in its form after being performed)
1189 * if true, the command was being 'undone'
1192 public void commandPerformed(CommandI command, boolean undo,
1193 VamsasSource source)
1195 for (CommandListener listener : commandListeners)
1197 listener.mirrorCommand(command, undo, this, source);
1202 * Returns a new CommandI representing the given command as mapped to the
1203 * given sequences. If no mapping could be made, or the command is not of a
1204 * mappable kind, returns null.
1212 public CommandI mapCommand(CommandI command, boolean undo,
1213 final AlignmentI mapTo, char gapChar)
1215 if (command instanceof EditCommand)
1217 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1218 mapTo, gapChar, seqmappings);
1220 else if (command instanceof OrderCommand)
1222 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1223 mapTo, seqmappings);