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.io.SiftsClient;
37 import jalview.util.MappingUtils;
38 import jalview.util.MessageManager;
40 import java.io.PrintStream;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Collections;
44 import java.util.Enumeration;
45 import java.util.HashMap;
46 import java.util.IdentityHashMap;
47 import java.util.LinkedHashSet;
48 import java.util.List;
51 import java.util.Vector;
54 import MCview.PDBChain;
55 import MCview.PDBfile;
57 public class StructureSelectionManager
59 public final static String NEWLINE = System.lineSeparator();
61 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
63 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
65 private boolean processSecondaryStructure = false;
67 private boolean secStructServices = false;
69 private boolean addTempFacAnnot = false;
72 * Set of any registered mappings between (dataset) sequences.
74 public Set<AlignedCodonFrame> seqmappings = new LinkedHashSet<AlignedCodonFrame>();
76 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
78 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
81 * @return true if will try to use external services for processing secondary
84 public boolean isSecStructServices()
86 return secStructServices;
90 * control use of external services for processing secondary structure
92 * @param secStructServices
94 public void setSecStructServices(boolean secStructServices)
96 this.secStructServices = secStructServices;
100 * flag controlling addition of any kind of structural annotation
102 * @return true if temperature factor annotation will be added
104 public boolean isAddTempFacAnnot()
106 return addTempFacAnnot;
110 * set flag controlling addition of structural annotation
112 * @param addTempFacAnnot
114 public void setAddTempFacAnnot(boolean addTempFacAnnot)
116 this.addTempFacAnnot = addTempFacAnnot;
121 * @return if true, the structure manager will attempt to add secondary
122 * structure lines for unannotated sequences
125 public boolean isProcessSecondaryStructure()
127 return processSecondaryStructure;
131 * Control whether structure manager will try to annotate mapped sequences
132 * with secondary structure from PDB data.
136 public void setProcessSecondaryStructure(boolean enable)
138 processSecondaryStructure = enable;
142 * debug function - write all mappings to stdout
144 public void reportMapping()
146 if (mappings.isEmpty())
148 System.err.println("reportMapping: No PDB/Sequence mappings.");
152 System.err.println("reportMapping: There are " + mappings.size()
155 for (StructureMapping sm : mappings)
157 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
163 * map between the PDB IDs (or structure identifiers) used by Jalview and the
164 * absolute filenames for PDB data that corresponds to it
166 Map<String, String> pdbIdFileName = new HashMap<String, String>();
168 Map<String, String> pdbFileNameId = new HashMap<String, String>();
170 public void registerPDBFile(String idForFile, String absoluteFile)
172 pdbIdFileName.put(idForFile, absoluteFile);
173 pdbFileNameId.put(absoluteFile, idForFile);
176 public String findIdForPDBFile(String idOrFile)
178 String id = pdbFileNameId.get(idOrFile);
182 public String findFileForPDBId(String idOrFile)
184 String id = pdbIdFileName.get(idOrFile);
188 public boolean isPDBFileRegistered(String idOrFile)
190 return pdbFileNameId.containsKey(idOrFile)
191 || pdbIdFileName.containsKey(idOrFile);
194 private static StructureSelectionManager nullProvider = null;
196 public static StructureSelectionManager getStructureSelectionManager(
197 StructureSelectionManagerProvider context)
201 if (nullProvider == null)
203 if (instances != null)
207 .getString("error.implementation_error_structure_selection_manager_null"),
208 new NullPointerException(MessageManager
209 .getString("exception.ssm_context_is_null")));
213 nullProvider = new StructureSelectionManager();
218 if (instances == null)
220 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
222 StructureSelectionManager instance = instances.get(context);
223 if (instance == null)
225 if (nullProvider != null)
227 instance = nullProvider;
231 instance = new StructureSelectionManager();
233 instances.put(context, instance);
239 * flag controlling whether SeqMappings are relayed from received sequence
240 * mouse over events to other sequences
242 boolean relaySeqMappings = true;
245 * Enable or disable relay of seqMapping events to other sequences. You might
246 * want to do this if there are many sequence mappings and the host computer
251 public void setRelaySeqMappings(boolean relay)
253 relaySeqMappings = relay;
257 * get the state of the relay seqMappings flag.
259 * @return true if sequence mouse overs are being relayed to other mapped
262 public boolean isRelaySeqMappingsEnabled()
264 return relaySeqMappings;
267 Vector listeners = new Vector();
270 * register a listener for alignment sequence mouseover events
274 public void addStructureViewerListener(Object svl)
276 if (!listeners.contains(svl))
278 listeners.addElement(svl);
283 * Returns the file name for a mapped PDB id (or null if not mapped).
288 public String alreadyMappedToFile(String pdbid)
290 for (StructureMapping sm : mappings)
292 if (sm.getPdbId().equals(pdbid))
301 * Import structure data and register a structure mapping for broadcasting
302 * colouring, mouseovers and selection events (convenience wrapper).
305 * - one or more sequences to be mapped to pdbFile
306 * @param targetChains
307 * - optional chain specification for mapping each sequence to pdb
308 * (may be nill, individual elements may be nill)
310 * - structure data resource
312 * - how to resolve data from resource
313 * @return null or the structure data parsed as a pdb file
315 synchronized public PDBfile setMapping(SequenceI[] sequence,
316 String[] targetChains, String pdbFile, String protocol)
318 return setMapping(true, sequence, targetChains, pdbFile, protocol);
322 * create sequence structure mappings between each sequence and the given
323 * pdbFile (retrieved via the given protocol).
325 * @param forStructureView
326 * when true, record the mapping for use in mouseOvers
329 * - one or more sequences to be mapped to pdbFile
330 * @param targetChains
331 * - optional chain specification for mapping each sequence to pdb
332 * (may be nill, individual elements may be nill)
334 * - structure data resource
336 * - how to resolve data from resource
337 * @return null or the structure data parsed as a pdb file
339 synchronized public PDBfile setMapping(boolean forStructureView,
340 SequenceI[] sequence, String[] targetChains, String pdbFile,
344 * There will be better ways of doing this in the future, for now we'll use
345 * the tried and tested MCview pdb mapping
347 boolean parseSecStr = processSecondaryStructure;
348 if (isPDBFileRegistered(pdbFile))
350 for (SequenceI sq : sequence)
353 while (ds.getDatasetSequence() != null)
355 ds = ds.getDatasetSequence();
358 if (ds.getAnnotation() != null)
360 for (AlignmentAnnotation ala : ds.getAnnotation())
362 // false if any annotation present from this structure
363 // JBPNote this fails for jmol/chimera view because the *file* is
364 // passed, not the structure data ID -
365 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
376 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
378 if (pdb.id != null && pdb.id.trim().length() > 0
379 && AppletFormatAdapter.FILE.equals(protocol))
381 registerPDBFile(pdb.id.trim(), pdbFile);
383 } catch (Exception ex)
385 ex.printStackTrace();
390 for (int s = 0; s < sequence.length; s++)
392 boolean infChain = true;
393 final SequenceI seq = sequence[s];
394 if (targetChains != null && targetChains[s] != null)
397 targetChain = targetChains[s];
399 else if (seq.getName().indexOf("|") > -1)
401 targetChain = seq.getName().substring(
402 seq.getName().lastIndexOf("|") + 1);
403 if (targetChain.length() > 1)
405 if (targetChain.trim().length() == 0)
411 // not a valid chain identifier
422 * Attempt pairwise alignment of the sequence with each chain in the PDB,
423 * and remember the highest scoring chain
426 AlignSeq maxAlignseq = null;
427 String maxChainId = " ";
428 PDBChain maxChain = null;
429 boolean first = true;
430 for (PDBChain chain : pdb.chains)
432 if (targetChain.length() > 0 && !targetChain.equals(chain.id)
435 continue; // don't try to map chains don't match.
437 // TODO: correctly determine sequence type for mixed na/peptide
439 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
440 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
443 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
444 // as.calcScoreMatrix();
445 // as.traceAlignment();
447 if (first || as.maxscore > max
448 || (as.maxscore == max && chain.id.equals(targetChain)))
454 maxChainId = chain.id;
457 if (maxChain == null)
461 final StringBuilder mappingDetails = new StringBuilder(128);
462 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
463 .append(NEWLINE).append("Sequence = ")
464 .append(maxChain.sequence.getSequenceAsString());
465 mappingDetails.append(NEWLINE).append("No of residues = ")
466 .append(maxChain.residues.size()).append(NEWLINE)
468 PrintStream ps = new PrintStream(System.out)
471 public void print(String x)
473 mappingDetails.append(x);
477 public void println()
479 mappingDetails.append(NEWLINE);
483 // mapWithNWAlignment();
485 maxAlignseq.printAlignment(ps);
487 mappingDetails.append(NEWLINE).append("PDB start/end ");
488 mappingDetails.append(String.valueOf(maxAlignseq.seq2start)).append(
490 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
491 mappingDetails.append(NEWLINE).append("SEQ start/end ");
492 // TODO JAL-1887 should be fixed from here
493 mappingDetails.append(
494 String.valueOf(maxAlignseq.seq1start + seq.getStart() - 1))
496 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
497 + seq.getEnd() - 1));
499 maxChain.makeExactMapping(maxAlignseq, seq);
500 jalview.datamodel.Mapping sqmpping = maxAlignseq
501 .getMappingFromS1(false);
502 jalview.datamodel.Mapping omap = new jalview.datamodel.Mapping(
503 sqmpping.getMap().getInverse());
504 maxChain.transferRESNUMFeatures(seq, null);
506 // allocate enough slots to store the mapping from positions in
507 // sequence[s] to the associated chain
508 int[][] mapping = new int[seq.findPosition(seq.getLength()) + 2][2];
514 Atom tmp = maxChain.atoms.elementAt(index);
515 if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
517 resNum = tmp.resNumber;
518 if (tmp.alignmentMapping >= -1)
520 // TODO (JAL-1836) address root cause: negative residue no in PDB
522 mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber;
523 mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex;
528 } while (index < maxChain.atoms.size());
530 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
532 pdbFile = "INLINE" + pdb.id;
534 // StructureMapping newMapping = new StructureMapping(seq, pdbFile,
535 // pdb.id, maxChainId, mapping, mappingDetails.toString());
536 StructureMapping newMapping = new SiftsClient(pdb.id)
537 .getSiftsMappingsFor(seq, pdbFile, maxChainId);
538 if (forStructureView)
540 mappings.add(newMapping);
542 maxChain.transferResidueAnnotation(newMapping, sqmpping);
549 private StructureMapping mapWithNWAlignment(StringBuilder mappingDetails,
550 PDBChain maxChain, AlignSeq maxAlignseq, SequenceI seq,
553 maxAlignseq.printAlignment(ps);
555 mappingDetails.append(NEWLINE).append("PDB start/end ");
556 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
558 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
559 mappingDetails.append(NEWLINE).append("SEQ start/end ");
560 // TODO JAL-1887 should be fixed from here
561 mappingDetails.append(
562 String.valueOf(maxAlignseq.seq1start + seq.getStart() - 1))
564 mappingDetails.append(String.valueOf(maxAlignseq.seq1end + seq.getEnd()
567 maxChain.makeExactMapping(maxAlignseq, seq);
568 jalview.datamodel.Mapping sqmpping = maxAlignseq
569 .getMappingFromS1(false);
570 jalview.datamodel.Mapping omap = new jalview.datamodel.Mapping(sqmpping
571 .getMap().getInverse());
572 maxChain.transferRESNUMFeatures(seq, null);
574 // allocate enough slots to store the mapping from positions in
575 // sequence[s] to the associated chain
576 int[][] mapping = new int[seq.findPosition(seq.getLength()) + 2][2];
582 Atom tmp = maxChain.atoms.elementAt(index);
583 if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
585 resNum = tmp.resNumber;
586 if (tmp.alignmentMapping >= -1)
588 // TODO (JAL-1836) address root cause: negative residue no in PDB
590 mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber;
591 mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex;
596 } while (index < maxChain.atoms.size());
601 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
603 listeners.removeElement(svl);
604 if (svl instanceof SequenceListener)
606 for (int i = 0; i < listeners.size(); i++)
608 if (listeners.elementAt(i) instanceof StructureListener)
610 ((StructureListener) listeners.elementAt(i))
611 .releaseReferences(svl);
616 if (pdbfiles == null)
622 * Remove mappings to the closed listener's PDB files, but first check if
623 * another listener is still interested
625 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
627 StructureListener sl;
628 for (int i = 0; i < listeners.size(); i++)
630 if (listeners.elementAt(i) instanceof StructureListener)
632 sl = (StructureListener) listeners.elementAt(i);
633 for (String pdbfile : sl.getPdbFile())
635 pdbs.remove(pdbfile);
641 * Rebuild the mappings set, retaining only those which are for 'other' PDB
646 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
647 for (StructureMapping sm : mappings)
649 if (!pdbs.contains(sm.pdbfile))
660 * Propagate mouseover of a single position in a structure
666 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
668 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
669 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
670 mouseOverStructure(atoms);
674 * Propagate mouseover or selection of multiple positions in a structure
678 public void mouseOverStructure(List<AtomSpec> atoms)
680 if (listeners == null)
682 // old or prematurely sent event
685 boolean hasSequenceListener = false;
686 for (int i = 0; i < listeners.size(); i++)
688 if (listeners.elementAt(i) instanceof SequenceListener)
690 hasSequenceListener = true;
693 if (!hasSequenceListener)
698 SearchResults results = new SearchResults();
699 for (AtomSpec atom : atoms)
701 SequenceI lastseq = null;
703 for (StructureMapping sm : mappings)
705 if (sm.pdbfile.equals(atom.getPdbFile())
706 && sm.pdbchain.equals(atom.getChain()))
708 int indexpos = sm.getSeqPos(atom.getPdbResNum());
709 if (lastipos != indexpos && lastseq != sm.sequence)
711 results.addResult(sm.sequence, indexpos, indexpos);
713 lastseq = sm.sequence;
714 // construct highlighted sequence list
715 for (AlignedCodonFrame acf : seqmappings)
717 acf.markMappedRegion(sm.sequence, indexpos, results);
723 for (Object li : listeners)
725 if (li instanceof SequenceListener)
727 ((SequenceListener) li).highlightSequence(results);
733 * highlight regions associated with a position (indexpos) in seq
736 * the sequence that the mouse over occurred on
738 * the absolute position being mouseovered in seq (0 to seq.length())
740 * the sequence position (if -1, seq.findPosition is called to
741 * resolve the residue number)
743 public void mouseOverSequence(SequenceI seq, int indexpos, int index,
746 boolean hasSequenceListeners = handlingVamsasMo
747 || !seqmappings.isEmpty();
748 SearchResults results = null;
751 index = seq.findPosition(indexpos);
753 for (int i = 0; i < listeners.size(); i++)
755 Object listener = listeners.elementAt(i);
756 if (listener == source)
758 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
759 // Temporary fudge with SequenceListener.getVamsasSource()
762 if (listener instanceof StructureListener)
764 highlightStructure((StructureListener) listener, seq, index);
768 if (listener instanceof SequenceListener)
770 final SequenceListener seqListener = (SequenceListener) listener;
771 if (hasSequenceListeners
772 && seqListener.getVamsasSource() != source)
774 if (relaySeqMappings)
778 results = MappingUtils.buildSearchResults(seq, index,
781 if (handlingVamsasMo)
783 results.addResult(seq, index, index);
786 if (!results.isEmpty())
788 seqListener.highlightSequence(results);
793 else if (listener instanceof VamsasListener && !handlingVamsasMo)
795 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
798 else if (listener instanceof SecondaryStructureListener)
800 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
808 * Send suitable messages to a StructureListener to highlight atoms
809 * corresponding to the given sequence position.
815 protected void highlightStructure(StructureListener sl, SequenceI seq,
818 if (!sl.isListeningFor(seq))
823 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
824 for (StructureMapping sm : mappings)
826 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence())
828 atomNo = sm.getAtomNum(index);
832 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
833 .getPDBResNum(index), atomNo));
837 sl.highlightAtoms(atoms);
841 * true if a mouse over event from an external (ie Vamsas) source is being
844 boolean handlingVamsasMo = false;
849 * as mouseOverSequence but only route event to SequenceListeners
853 * in an alignment sequence
855 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
858 handlingVamsasMo = true;
859 long msg = sequenceI.hashCode() * (1 + position);
863 mouseOverSequence(sequenceI, position, -1, source);
865 handlingVamsasMo = false;
868 public Annotation[] colourSequenceFromStructure(SequenceI seq,
872 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
873 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
875 * Annotation [] annotations = new Annotation[seq.getLength()];
877 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
878 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
879 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
881 * for (int j = 0; j < mappings.length; j++) {
883 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
884 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
885 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
886 * "+mappings[j].pdbfile);
888 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
889 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
891 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
892 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
893 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
894 * mappings[j].pdbfile); }
896 * annotations[index] = new Annotation("X",null,' ',0,col); } return
897 * annotations; } } } }
899 * return annotations;
903 public void structureSelectionChanged()
907 public void sequenceSelectionChanged()
911 public void sequenceColoursChanged(Object source)
913 StructureListener sl;
914 for (int i = 0; i < listeners.size(); i++)
916 if (listeners.elementAt(i) instanceof StructureListener)
918 sl = (StructureListener) listeners.elementAt(i);
919 sl.updateColours(source);
924 public StructureMapping[] getMapping(String pdbfile)
926 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
927 for (StructureMapping sm : mappings)
929 if (sm.pdbfile.equals(pdbfile))
934 return tmp.toArray(new StructureMapping[tmp.size()]);
938 * Returns a readable description of all mappings for the given pdbfile to any
939 * of the given sequences
945 public String printMappings(String pdbfile, List<SequenceI> seqs)
947 if (pdbfile == null || seqs == null || seqs.isEmpty())
952 StringBuilder sb = new StringBuilder(64);
953 for (StructureMapping sm : mappings)
955 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
957 sb.append(sm.mappingDetails);
959 // separator makes it easier to read multiple mappings
960 sb.append("=====================");
966 return sb.toString();
970 * Remove the given mapping
974 public void deregisterMapping(AlignedCodonFrame acf)
978 boolean removed = seqmappings.remove(acf);
979 if (removed && seqmappings.isEmpty())
981 System.out.println("All mappings removed");
987 * Add each of the given codonFrames to the stored set, if not aready present.
991 public void registerMappings(Set<AlignedCodonFrame> set)
995 for (AlignedCodonFrame acf : set)
997 registerMapping(acf);
1003 * Add the given mapping to the stored set, unless already stored.
1005 public void registerMapping(AlignedCodonFrame acf)
1009 if (!seqmappings.contains(acf))
1011 seqmappings.add(acf);
1017 * Resets this object to its initial state by removing all registered
1018 * listeners, codon mappings, PDB file mappings
1020 public void resetAll()
1022 if (mappings != null)
1026 if (seqmappings != null)
1028 seqmappings.clear();
1030 if (sel_listeners != null)
1032 sel_listeners.clear();
1034 if (listeners != null)
1038 if (commandListeners != null)
1040 commandListeners.clear();
1042 if (view_listeners != null)
1044 view_listeners.clear();
1046 if (pdbFileNameId != null)
1048 pdbFileNameId.clear();
1050 if (pdbIdFileName != null)
1052 pdbIdFileName.clear();
1056 public void addSelectionListener(SelectionListener selecter)
1058 if (!sel_listeners.contains(selecter))
1060 sel_listeners.add(selecter);
1064 public void removeSelectionListener(SelectionListener toremove)
1066 if (sel_listeners.contains(toremove))
1068 sel_listeners.remove(toremove);
1072 public synchronized void sendSelection(
1073 jalview.datamodel.SequenceGroup selection,
1074 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1076 for (SelectionListener slis : sel_listeners)
1080 slis.selection(selection, colsel, source);
1085 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1087 public synchronized void sendViewPosition(
1088 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1089 int startSeq, int endSeq)
1092 if (view_listeners != null && view_listeners.size() > 0)
1094 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1096 while (listeners.hasMoreElements())
1098 AlignmentViewPanelListener slis = listeners.nextElement();
1101 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1109 * release all references associated with this manager provider
1111 * @param jalviewLite
1113 public static void release(StructureSelectionManagerProvider jalviewLite)
1115 // synchronized (instances)
1117 if (instances == null)
1121 StructureSelectionManager mnger = (instances.get(jalviewLite));
1124 instances.remove(jalviewLite);
1128 } catch (Throwable x)
1135 public void registerPDBEntry(PDBEntry pdbentry)
1137 if (pdbentry.getFile() != null
1138 && pdbentry.getFile().trim().length() > 0)
1140 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1144 public void addCommandListener(CommandListener cl)
1146 if (!commandListeners.contains(cl))
1148 commandListeners.add(cl);
1152 public boolean hasCommandListener(CommandListener cl)
1154 return this.commandListeners.contains(cl);
1157 public boolean removeCommandListener(CommandListener l)
1159 return commandListeners.remove(l);
1163 * Forward a command to any command listeners (except for the command's
1167 * the command to be broadcast (in its form after being performed)
1169 * if true, the command was being 'undone'
1172 public void commandPerformed(CommandI command, boolean undo,
1173 VamsasSource source)
1175 for (CommandListener listener : commandListeners)
1177 listener.mirrorCommand(command, undo, this, source);
1182 * Returns a new CommandI representing the given command as mapped to the
1183 * given sequences. If no mapping could be made, or the command is not of a
1184 * mappable kind, returns null.
1192 public CommandI mapCommand(CommandI command, boolean undo,
1193 final AlignmentI mapTo, char gapChar)
1195 if (command instanceof EditCommand)
1197 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1198 mapTo, gapChar, seqmappings);
1200 else if (command instanceof OrderCommand)
1202 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1203 mapTo, seqmappings);