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;
40 import jalview.ws.sifts.SiftsSettings;
42 import java.io.PrintStream;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.Enumeration;
47 import java.util.HashMap;
48 import java.util.IdentityHashMap;
49 import java.util.LinkedHashSet;
50 import java.util.List;
53 import java.util.Vector;
56 import MCview.PDBChain;
57 import MCview.PDBfile;
59 public class StructureSelectionManager
61 public final static String NEWLINE = System.lineSeparator();
63 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
65 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
67 private boolean processSecondaryStructure = false;
69 private boolean secStructServices = false;
71 private boolean addTempFacAnnot = false;
74 * Set of any registered mappings between (dataset) sequences.
76 public Set<AlignedCodonFrame> seqmappings = new LinkedHashSet<AlignedCodonFrame>();
78 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
80 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
83 * @return true if will try to use external services for processing secondary
86 public boolean isSecStructServices()
88 return secStructServices;
92 * control use of external services for processing secondary structure
94 * @param secStructServices
96 public void setSecStructServices(boolean secStructServices)
98 this.secStructServices = secStructServices;
102 * flag controlling addition of any kind of structural annotation
104 * @return true if temperature factor annotation will be added
106 public boolean isAddTempFacAnnot()
108 return addTempFacAnnot;
112 * set flag controlling addition of structural annotation
114 * @param addTempFacAnnot
116 public void setAddTempFacAnnot(boolean addTempFacAnnot)
118 this.addTempFacAnnot = addTempFacAnnot;
123 * @return if true, the structure manager will attempt to add secondary
124 * structure lines for unannotated sequences
127 public boolean isProcessSecondaryStructure()
129 return processSecondaryStructure;
133 * Control whether structure manager will try to annotate mapped sequences
134 * with secondary structure from PDB data.
138 public void setProcessSecondaryStructure(boolean enable)
140 processSecondaryStructure = enable;
144 * debug function - write all mappings to stdout
146 public void reportMapping()
148 if (mappings.isEmpty())
150 System.err.println("reportMapping: No PDB/Sequence mappings.");
154 System.err.println("reportMapping: There are " + mappings.size()
157 for (StructureMapping sm : mappings)
159 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
165 * map between the PDB IDs (or structure identifiers) used by Jalview and the
166 * absolute filenames for PDB data that corresponds to it
168 Map<String, String> pdbIdFileName = new HashMap<String, String>();
170 Map<String, String> pdbFileNameId = new HashMap<String, String>();
172 public void registerPDBFile(String idForFile, String absoluteFile)
174 pdbIdFileName.put(idForFile, absoluteFile);
175 pdbFileNameId.put(absoluteFile, idForFile);
178 public String findIdForPDBFile(String idOrFile)
180 String id = pdbFileNameId.get(idOrFile);
184 public String findFileForPDBId(String idOrFile)
186 String id = pdbIdFileName.get(idOrFile);
190 public boolean isPDBFileRegistered(String idOrFile)
192 return pdbFileNameId.containsKey(idOrFile)
193 || pdbIdFileName.containsKey(idOrFile);
196 private static StructureSelectionManager nullProvider = null;
198 public static StructureSelectionManager getStructureSelectionManager(
199 StructureSelectionManagerProvider context)
203 if (nullProvider == null)
205 if (instances != null)
209 .getString("error.implementation_error_structure_selection_manager_null"),
210 new NullPointerException(MessageManager
211 .getString("exception.ssm_context_is_null")));
215 nullProvider = new StructureSelectionManager();
220 if (instances == null)
222 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
224 StructureSelectionManager instance = instances.get(context);
225 if (instance == null)
227 if (nullProvider != null)
229 instance = nullProvider;
233 instance = new StructureSelectionManager();
235 instances.put(context, instance);
241 * flag controlling whether SeqMappings are relayed from received sequence
242 * mouse over events to other sequences
244 boolean relaySeqMappings = true;
247 * Enable or disable relay of seqMapping events to other sequences. You might
248 * want to do this if there are many sequence mappings and the host computer
253 public void setRelaySeqMappings(boolean relay)
255 relaySeqMappings = relay;
259 * get the state of the relay seqMappings flag.
261 * @return true if sequence mouse overs are being relayed to other mapped
264 public boolean isRelaySeqMappingsEnabled()
266 return relaySeqMappings;
269 Vector listeners = new Vector();
272 * register a listener for alignment sequence mouseover events
276 public void addStructureViewerListener(Object svl)
278 if (!listeners.contains(svl))
280 listeners.addElement(svl);
285 * Returns the file name for a mapped PDB id (or null if not mapped).
290 public String alreadyMappedToFile(String pdbid)
292 for (StructureMapping sm : mappings)
294 if (sm.getPdbId().equals(pdbid))
303 * Import structure data and register a structure mapping for broadcasting
304 * colouring, mouseovers and selection events (convenience wrapper).
307 * - one or more sequences to be mapped to pdbFile
308 * @param targetChains
309 * - optional chain specification for mapping each sequence to pdb
310 * (may be nill, individual elements may be nill)
312 * - structure data resource
314 * - how to resolve data from resource
315 * @return null or the structure data parsed as a pdb file
317 synchronized public PDBfile setMapping(SequenceI[] sequence,
318 String[] targetChains, String pdbFile, String protocol)
320 return setMapping(true, sequence, targetChains, pdbFile, protocol);
324 * create sequence structure mappings between each sequence and the given
325 * pdbFile (retrieved via the given protocol).
327 * @param forStructureView
328 * when true, record the mapping for use in mouseOvers
330 * @param sequenceArray
331 * - one or more sequences to be mapped to pdbFile
332 * @param targetChainIds
333 * - optional chain specification for mapping each sequence to pdb
334 * (may be nill, individual elements may be nill)
336 * - structure data resource
338 * - how to resolve data from resource
339 * @return null or the structure data parsed as a pdb file
341 synchronized public PDBfile setMapping(boolean forStructureView,
342 SequenceI[] sequenceArray, String[] targetChainIds,
347 * There will be better ways of doing this in the future, for now we'll use
348 * the tried and tested MCview pdb mapping
350 boolean parseSecStr = processSecondaryStructure;
351 if (isPDBFileRegistered(pdbFile))
353 for (SequenceI sq : sequenceArray)
356 while (ds.getDatasetSequence() != null)
358 ds = ds.getDatasetSequence();
361 if (ds.getAnnotation() != null)
363 for (AlignmentAnnotation ala : ds.getAnnotation())
365 // false if any annotation present from this structure
366 // JBPNote this fails for jmol/chimera view because the *file* is
367 // passed, not the structure data ID -
368 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
377 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
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);