1 /*  $Id: messenger.cpp 104942 2007-05-31 20:08:39Z thiessen $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors:  Paul Thiessen
27 *
28 * File Description:
29 *      Classes to handle messaging and communication between sequence
30 *      and structure windows
31 *
32 * ===========================================================================
33 */
34 
35 #include <ncbi_pch.hpp>
36 #include <corelib/ncbistd.hpp>
37 
38 #include <memory>
39 
40 #include <objects/mmdb1/Biostruc_id.hpp>
41 #include <objects/mmdb1/Mmdb_id.hpp>
42 #include <objects/mmdb3/Biostruc_feature_set.hpp>
43 #include <objects/mmdb3/Biostruc_feature_set_id.hpp>
44 #include <objects/mmdb3/Biostruc_feature.hpp>
45 #include <objects/mmdb3/Chem_graph_pntrs.hpp>
46 #include <objects/mmdb3/Residue_pntrs.hpp>
47 #include <objects/mmdb3/Residue_interval_pntr.hpp>
48 #include <objects/mmdb1/Molecule_id.hpp>
49 #include <objects/mmdb1/Residue_id.hpp>
50 
51 #include "remove_header_conflicts.hpp"
52 
53 #include "messenger.hpp"
54 #include "structure_window.hpp"
55 #include "cn3d_glcanvas.hpp"
56 #include "sequence_viewer.hpp"
57 #include "opengl_renderer.hpp"
58 #include "structure_set.hpp"
59 #include "chemical_graph.hpp"
60 #include "sequence_set.hpp"
61 #include "molecule_identifier.hpp"
62 #include "cn3d_tools.hpp"
63 
64 USING_NCBI_SCOPE;
65 USING_SCOPE(objects);
66 
67 
68 BEGIN_SCOPE(Cn3D)
69 
70 // the global Messenger object
71 static Messenger messenger;
72 
GlobalMessenger(void)73 Messenger * GlobalMessenger(void)
74 {
75     return &messenger;
76 }
77 
78 
PostRedrawAllStructures(void)79 void Messenger::PostRedrawAllStructures(void)
80 {
81     redrawAllStructures = true;
82     redrawMolecules.clear();
83 }
84 
PostRedrawMolecule(const Molecule * molecule)85 void Messenger::PostRedrawMolecule(const Molecule *molecule)
86 {
87     if (!redrawAllStructures) redrawMolecules[molecule] = true;
88 }
89 
PostRedrawAllSequenceViewers(void)90 void Messenger::PostRedrawAllSequenceViewers(void)
91 {
92     redrawAllSequenceViewers = true;
93     redrawSequenceViewers.clear();
94 }
PostRedrawSequenceViewer(ViewerBase * viewer)95 void Messenger::PostRedrawSequenceViewer(ViewerBase *viewer)
96 {
97     if (!redrawAllSequenceViewers) redrawSequenceViewers[viewer] = true;
98 }
99 
UnPostRedrawAllSequenceViewers(void)100 void Messenger::UnPostRedrawAllSequenceViewers(void)
101 {
102     redrawAllSequenceViewers = false;
103     redrawSequenceViewers.clear();
104 }
105 
UnPostRedrawSequenceViewer(ViewerBase * viewer)106 void Messenger::UnPostRedrawSequenceViewer(ViewerBase *viewer)
107 {
108     if (redrawAllSequenceViewers) {
109         SequenceViewerList::const_iterator q, qe = sequenceViewers.end();
110         for (q=sequenceViewers.begin(); q!=qe; ++q) redrawSequenceViewers[*q] = true;
111         redrawAllSequenceViewers = false;
112     }
113     RedrawSequenceViewerList::iterator f = redrawSequenceViewers.find(viewer);
114     if (f != redrawSequenceViewers.end()) redrawSequenceViewers.erase(f);
115 }
116 
UnPostStructureRedraws(void)117 void Messenger::UnPostStructureRedraws(void)
118 {
119     redrawAllStructures = false;
120     redrawMolecules.clear();
121 }
122 
ProcessRedraws(void)123 void Messenger::ProcessRedraws(void)
124 {
125     if (redrawAllSequenceViewers) {
126         SequenceViewerList::const_iterator q, qe = sequenceViewers.end();
127         for (q=sequenceViewers.begin(); q!=qe; ++q) (*q)->Refresh();
128         redrawAllSequenceViewers = false;
129     }
130     else if (redrawSequenceViewers.size() > 0) {
131         RedrawSequenceViewerList::const_iterator q, qe = redrawSequenceViewers.end();
132         for (q=redrawSequenceViewers.begin(); q!=qe; ++q) q->first->Refresh();
133         redrawSequenceViewers.clear();
134     }
135 
136     if (redrawAllStructures) {
137         if (structureWindow) {
138             structureWindow->glCanvas->SetCurrent();
139             structureWindow->glCanvas->renderer->Construct();
140             structureWindow->glCanvas->renderer->NewView();
141             structureWindow->glCanvas->Refresh(false);
142         }
143 		redrawAllStructures = false;
144     }
145     else if (redrawMolecules.size() > 0) {
146         map < const StructureObject * , bool > hetsRedrawn;
147         RedrawMoleculeList::const_iterator m, me = redrawMolecules.end();
148         for (m=redrawMolecules.begin(); m!=me; ++m) {
149             const StructureObject *object;
150             if (!m->first->GetParentOfType(&object)) continue;
151 
152             // hets/solvents are always redrawn with each molecule, so don't need to repeat
153             if ((m->first->IsSolvent() || m->first->IsHeterogen()) &&
154                 hetsRedrawn.find(object) != hetsRedrawn.end()) continue;
155 
156             object->graph->RedrawMolecule(m->first->id);
157             hetsRedrawn[object] = true;
158         }
159         if (structureWindow) {
160             structureWindow->glCanvas->renderer->NewView();
161             structureWindow->glCanvas->Refresh(false);
162         }
163         redrawMolecules.clear();
164     }
165 }
166 
RemoveStructureWindow(const StructureWindow * window)167 void Messenger::RemoveStructureWindow(const StructureWindow *window)
168 {
169     if (window != structureWindow)
170         ERRORMSG("Messenger::RemoveStructureWindow() - window mismatch");
171     structureWindow = NULL;
172 }
173 
RemoveSequenceViewer(const ViewerBase * sequenceViewer)174 void Messenger::RemoveSequenceViewer(const ViewerBase *sequenceViewer)
175 {
176     SequenceViewerList::iterator t, te = sequenceViewers.end();
177     for (t=sequenceViewers.begin(); t!=te; ++t) {
178         if (*t == sequenceViewer) sequenceViewers.erase(t);
179         break;
180     }
181 }
182 
SequenceWindowsSave(bool prompt)183 void Messenger::SequenceWindowsSave(bool prompt)
184 {
185     SequenceViewerList::const_iterator q, qe = sequenceViewers.end();
186     for (q=sequenceViewers.begin(); q!=qe; ++q)
187         (*q)->SaveDialog(prompt);
188 }
189 
NewSequenceViewerFont(void)190 void Messenger::NewSequenceViewerFont(void)
191 {
192     SequenceViewerList::const_iterator q, qe = sequenceViewers.end();
193     for (q=sequenceViewers.begin(); q!=qe; ++q)
194         (*q)->NewFont();
195 }
196 
197 
198 ///// highlighting functions /////
199 
IsHighlighted(const MoleculeIdentifier * identifier,int index) const200 bool Messenger::IsHighlighted(const MoleculeIdentifier *identifier, int index) const
201 {
202     if (highlightingSuspended) return false;
203 
204     MoleculeHighlightMap::const_iterator h = highlights.find(identifier);
205     if (h == highlights.end()) return false;
206 
207     if (index == -1) return true;   // special check for highlight anywhere
208 
209     if (index < 0 || index >= (int)h->second.size()) {
210         ERRORMSG("Messenger::IsHighlighted() - index out of range");
211         return false;
212     } else
213         return h->second[index];
214 }
215 
IsHighlighted(const Molecule * molecule,int residueID) const216 bool Messenger::IsHighlighted(const Molecule *molecule, int residueID) const
217 {
218     return IsHighlighted(molecule->identifier, residueID - 1);  // assume index = id - 1
219 }
220 
IsHighlighted(const Sequence * sequence,unsigned int seqIndex) const221 bool Messenger::IsHighlighted(const Sequence *sequence, unsigned int seqIndex) const
222 {
223     return IsHighlighted(sequence->identifier, seqIndex);
224 }
225 
IsHighlightedAnywhere(const MoleculeIdentifier * identifier) const226 bool Messenger::IsHighlightedAnywhere(const MoleculeIdentifier *identifier) const
227 {
228     return IsHighlighted(identifier, -1);
229 }
230 
IsHighlightedAnywhere(const Molecule * molecule) const231 bool Messenger::IsHighlightedAnywhere(const Molecule *molecule) const
232 {
233     return IsHighlighted(molecule->identifier, -1);
234 }
235 
RedrawMoleculesWithIdentifier(const MoleculeIdentifier * identifier,const StructureSet * set)236 void Messenger::RedrawMoleculesWithIdentifier(const MoleculeIdentifier *identifier, const StructureSet *set)
237 {
238     StructureSet::ObjectList::const_iterator o, oe = set->objects.end();
239     ChemicalGraph::MoleculeMap::const_iterator m, me;
240     for (o=set->objects.begin(); o!=oe; ++o) {
241         for (m=(*o)->graph->molecules.begin(), me=(*o)->graph->molecules.end(); m!=me; ++m) {
242             if (m->second->identifier == identifier)
243                 PostRedrawMolecule(m->second);
244         }
245     }
246 }
247 
AddHighlights(const Sequence * sequence,unsigned int seqIndexFrom,unsigned int seqIndexTo)248 void Messenger::AddHighlights(const Sequence *sequence, unsigned int seqIndexFrom, unsigned int seqIndexTo)
249 {
250     if (seqIndexFrom > seqIndexTo || seqIndexFrom >= sequence->Length() || seqIndexTo >= sequence->Length()) {
251         ERRORMSG("Messenger::AddHighlights() - seqIndex out of range");
252         return;
253     }
254 
255     MoleculeHighlightMap::iterator h = highlights.find(sequence->identifier);
256     if (h == highlights.end()) {
257         highlights[sequence->identifier].resize(sequence->Length(), false);
258         h = highlights.find(sequence->identifier);
259     }
260 
261     for (unsigned int i=seqIndexFrom; i<=seqIndexTo; ++i) h->second[i] = true;
262 
263     PostRedrawAllSequenceViewers();
264     RedrawMoleculesWithIdentifier(sequence->identifier, sequence->parentSet);
265 }
266 
HighlightAndShowSequence(const Sequence * sequence)267 void Messenger::HighlightAndShowSequence(const Sequence *sequence)
268 {
269     RemoveAllHighlights(true);
270     AddHighlights(sequence, 0, sequence->Length() - 1);
271 
272     SequenceViewerList::const_iterator q, qe = sequenceViewers.end();
273     for (q=sequenceViewers.begin(); q!=qe; ++q)
274         (*q)->MakeSequenceVisible(sequence->identifier);
275 }
276 
KeepHighlightsOnlyOnSequence(const Sequence * sequence)277 void Messenger::KeepHighlightsOnlyOnSequence(const Sequence *sequence)
278 {
279     if (highlights.size() == 0 || (highlights.size() == 1 && highlights.begin()->first == sequence->identifier))
280         return;
281 
282     MoleculeHighlightMap newHighlights;
283     MoleculeHighlightMap::const_iterator h, he = highlights.end();
284     for (h=highlights.begin(); h!=he; ++h) {
285         if (h->first == sequence->identifier) {
286             newHighlights[sequence->identifier] = h->second;
287             break;
288         }
289     }
290     if (h == he) {
291         ERRORMSG("Selected sequence has no highlights!");
292         return;
293     }
294     highlights.clear();
295     highlights = newHighlights;
296     PostRedrawAllStructures();
297     PostRedrawAllSequenceViewers();
298 }
299 
RemoveHighlights(const Sequence * sequence,unsigned int seqIndexFrom,unsigned int seqIndexTo)300 void Messenger::RemoveHighlights(const Sequence *sequence, unsigned int seqIndexFrom, unsigned int seqIndexTo)
301 {
302     if (seqIndexFrom > seqIndexTo || seqIndexFrom >= sequence->Length() || seqIndexTo >= sequence->Length()) {
303         ERRORMSG("Messenger::RemoveHighlights() - seqIndex out of range");
304         return;
305     }
306 
307     MoleculeHighlightMap::iterator h = highlights.find(sequence->identifier);
308     if (h != highlights.end()) {
309         unsigned int i;
310         for (i=seqIndexFrom; i<=seqIndexTo; ++i) h->second[i] = false;
311 
312         // remove sequence from store if no highlights left
313         for (i=0; i<sequence->Length(); ++i)
314             if (h->second[i] == true) break;
315         if (i == sequence->Length())
316             highlights.erase(h);
317 
318         PostRedrawAllSequenceViewers();
319         RedrawMoleculesWithIdentifier(sequence->identifier, sequence->parentSet);
320     }
321 }
322 
ToggleHighlights(const MoleculeIdentifier * identifier,unsigned int indexFrom,unsigned int indexTo,const StructureSet * set)323 void Messenger::ToggleHighlights(const MoleculeIdentifier *identifier, unsigned int indexFrom, unsigned int indexTo,
324     const StructureSet *set)
325 {
326     if (indexFrom > indexTo || indexFrom >= identifier->nResidues || indexTo >= identifier->nResidues) {
327         ERRORMSG("Messenger::ToggleHighlights() - index out of range");
328         return;
329     }
330 
331     MoleculeHighlightMap::iterator h = highlights.find(identifier);
332     if (h == highlights.end()) {
333         highlights[identifier].resize(identifier->nResidues, false);
334         h = highlights.find(identifier);
335     }
336 
337     unsigned int i;
338     for (i=indexFrom; i<=indexTo; ++i) h->second[i] = !h->second[i];
339 
340     // remove sequence from store if no highlights left
341     for (i=0; i<h->second.size(); ++i)
342         if (h->second[i] == true) break;
343     if (i == h->second.size())
344         highlights.erase(h);
345 
346     PostRedrawAllSequenceViewers();
347     RedrawMoleculesWithIdentifier(identifier, set);
348 }
349 
ToggleHighlights(const Sequence * sequence,unsigned int seqIndexFrom,unsigned int seqIndexTo)350 void Messenger::ToggleHighlights(const Sequence *sequence, unsigned int seqIndexFrom, unsigned int seqIndexTo)
351 {
352     ToggleHighlights(sequence->identifier, seqIndexFrom, seqIndexTo, sequence->parentSet);
353 }
354 
AddHighlights(const Molecule * molecule,int residueIDFrom,int residueIDTo,bool scrollViewersTo)355 void Messenger::AddHighlights(const Molecule *molecule, int residueIDFrom, int residueIDTo, bool scrollViewersTo)
356 {
357     if (residueIDFrom > residueIDTo || residueIDFrom < 1 || residueIDTo < 1 ||
358             residueIDFrom > (int)molecule->NResidues() || residueIDTo > (int)molecule->NResidues()) {
359         ERRORMSG("Messenger::AddHighlights() - residueID out of range");
360         return;
361     }
362 
363     MoleculeHighlightMap::iterator h = highlights.find(molecule->identifier);
364     if (h == highlights.end()) {
365         highlights[molecule->identifier].resize(molecule->NResidues(), false);
366         h = highlights.find(molecule->identifier);
367     }
368 
369     // assume index = id - 1
370     for (int i=residueIDFrom-1; i<=residueIDTo-1; ++i) h->second[i] = true;
371 
372     if (scrollViewersTo) {
373         // make selected residue visible in sequence viewers if residue is in displayed sequence
374         SequenceViewerList::iterator t, te = sequenceViewers.end();
375         for (t=sequenceViewers.begin(); t!=te; ++t)
376             (*t)->MakeResidueVisible(molecule, residueIDFrom - 1);
377     }
378 }
379 
ToggleHighlight(const Molecule * molecule,int residueID,bool scrollViewersTo)380 void Messenger::ToggleHighlight(const Molecule *molecule, int residueID, bool scrollViewersTo)
381 {
382     // assume index = id - 1
383     ToggleHighlights(molecule->identifier, residueID - 1, residueID - 1, molecule->parentSet);
384 
385     if (scrollViewersTo) {
386         // make selected residue visible in sequence viewers if residue is in displayed sequence
387         SequenceViewerList::iterator t, te = sequenceViewers.end();
388         for (t=sequenceViewers.begin(); t!=te; ++t)
389             (*t)->MakeResidueVisible(molecule, residueID - 1);
390     }
391 }
392 
RemoveAllHighlights(bool postRedraws)393 bool Messenger::RemoveAllHighlights(bool postRedraws)
394 {
395     bool anyRemoved = highlights.size() > 0;
396 
397     if (postRedraws) {
398         if (anyRemoved) PostRedrawAllSequenceViewers();
399 
400         if (structureWindow) {
401             MoleculeHighlightMap::const_iterator h, he = highlights.end();
402             for (h=highlights.begin(); h!=he; ++h)
403                 RedrawMoleculesWithIdentifier(h->first, structureWindow->glCanvas->structureSet);
404         }
405     }
406 
407     highlights.clear();
408 
409     return anyRemoved;
410 }
411 
CacheHighlights(void)412 void Messenger::CacheHighlights(void)
413 {
414     highlightCache = highlights;
415 }
416 
RestoreCachedHighlights(void)417 void Messenger::RestoreCachedHighlights(void)
418 {
419     highlights = highlightCache;
420     PostRedrawAllSequenceViewers();
421     PostRedrawAllStructures();
422 }
423 
GetHighlights(MoleculeHighlightMap * copyHighlights)424 void Messenger::GetHighlights(MoleculeHighlightMap *copyHighlights)
425 {
426     *copyHighlights = highlights;    // copy the lists
427 }
428 
SetHighlights(const MoleculeHighlightMap & newHighlights)429 void Messenger::SetHighlights(const MoleculeHighlightMap& newHighlights)
430 {
431     RemoveAllHighlights(true);
432     highlights = newHighlights;
433 
434     PostRedrawAllSequenceViewers();
435     if (structureWindow) {
436         MoleculeHighlightMap::const_iterator h, he = highlights.end();
437         for (h=highlights.begin(); h!=he; ++h)
438             RedrawMoleculesWithIdentifier(h->first, structureWindow->glCanvas->structureSet);
439     }
440 }
441 
SuspendHighlighting(bool suspend)442 void Messenger::SuspendHighlighting(bool suspend)
443 {
444     if (highlightingSuspended != suspend) {
445         highlightingSuspended = suspend;
446         if (IsAnythingHighlighted()) {
447             PostRedrawAllStructures();
448             PostRedrawAllSequenceViewers();
449         }
450     }
451 }
452 
GetHighlightedResiduesWithStructure(MoleculeHighlightMap * residues) const453 bool Messenger::GetHighlightedResiduesWithStructure(MoleculeHighlightMap *residues) const
454 {
455     residues->clear();
456     if (!IsAnythingHighlighted()) return false;
457 
458     MoleculeHighlightMap::const_iterator h, he = highlights.end();
459     for (h=highlights.begin(); h!=he; ++h) {
460         if (h->first->HasStructure())
461             (*residues)[h->first] = h->second;
462     }
463 
464     return (residues->size() > 0);
465 }
466 
CreateBiostrucAnnotSetForHighlightsOnSingleObject(void) const467 CBiostruc_annot_set * Messenger::CreateBiostrucAnnotSetForHighlightsOnSingleObject(void) const
468 {
469     if (!IsAnythingHighlighted()) {
470         ERRORMSG("Nothing highlighted");
471         return NULL;
472     }
473 
474     // check to see that all highlights are on a single structure object
475     int mmdbID = 0;
476     MoleculeHighlightMap::const_iterator h, he = highlights.end();
477     for (h=highlights.begin(); h!=he; ++h) {
478         if (h == highlights.begin()) mmdbID = h->first->mmdbID;
479         if (h->first->mmdbID == MoleculeIdentifier::VALUE_NOT_SET || h->first->mmdbID != mmdbID) {
480             ERRORMSG("All highlights must be on a single PDB structure");
481             return NULL;
482         }
483         if (h->first->moleculeID == MoleculeIdentifier::VALUE_NOT_SET) {
484             ERRORMSG("internal error - MoleculeIdentifier has no moleculeID");
485             return NULL;
486         }
487     }
488 
489     // create the Biostruc-annot-set
490     CRef < CBiostruc_annot_set > bas(new CBiostruc_annot_set());
491 
492     // set id
493     CRef < CBiostruc_id > bid(new CBiostruc_id());
494     bas->SetId().push_back(bid);
495     bid->SetMmdb_id().Set(mmdbID);
496 
497     // create feature set and feature
498     CRef < CBiostruc_feature_set > bfs(new CBiostruc_feature_set());
499     bas->SetFeatures().push_back(bfs);
500     bfs->SetId().Set(1);
501     CRef < CBiostruc_feature > bf(new CBiostruc_feature());
502     bfs->SetFeatures().push_back(bf);
503 
504     // create Chem-graph-pntrs with residues
505     CChem_graph_pntrs *cgp = new CChem_graph_pntrs();
506     bf->SetLocation().SetSubgraph(*cgp);
507     CResidue_pntrs *rp = new CResidue_pntrs();
508     cgp->SetResidues(*rp);
509 
510     // add all residue intervals
511     for (h=highlights.begin(); h!=he; ++h) {
512         unsigned int first = 0, last = 0;
513         while (first < h->second.size()) {
514 
515             // find first highlighted residue
516             while (first < h->second.size() && !h->second[first]) ++first;
517             if (first >= h->second.size()) break;
518             // find last in contiguous stretch of highlighted residues
519             last = first;
520             while (last + 1 < h->second.size() && h->second[last + 1]) ++last;
521 
522             // add new interval to list
523             CRef < CResidue_interval_pntr > rip(new CResidue_interval_pntr());
524             rip->SetMolecule_id().Set(h->first->moleculeID);
525             rip->SetFrom().Set(first + 1);  // assume residueID == index + 1
526             rip->SetTo().Set(last + 1);
527             rp->SetInterval().push_back(rip);
528 
529             first = last + 2;
530         }
531     }
532 
533     return bas.Release();
534 }
535 
GetHighlightsForSelectionMessage(string * data) const536 bool Messenger::GetHighlightsForSelectionMessage(string *data) const
537 {
538     data->erase();
539     if (!IsAnythingHighlighted()) return false;
540 
541     CNcbiOstrstream oss;
542 
543     MoleculeHighlightMap::const_iterator h, he = highlights.end();
544     for (h=highlights.begin(); h!=he; ++h) {
545 
546         // add identifier
547         string id;
548         if (!SeqIdToIdentifier(h->first->seqIDs.front(), id)) {
549             WARNINGMSG("Messenger::GetHighlightsForSelectionMessage() - SeqIdToIdentifier() failed");
550             continue;
551         }
552         oss << id << '\t';  // separate id from intervals with tab
553 
554         // add range(s)
555         unsigned int first = 0, last = 0;
556         bool firstInterval = true;
557         while (first < h->second.size()) {
558 
559             // find first highlighted residue
560             while (first < h->second.size() && !h->second[first]) ++first;
561             if (first >= h->second.size()) break;
562 
563             // find last in contiguous stretch of highlighted residues
564             last = first;
565             while (last + 1 < h->second.size() && h->second[last + 1]) ++last;
566 
567             // add new interval to list (separated by spaces)
568             if (!firstInterval)
569                 oss << ' ';
570             else
571                 firstInterval = false;
572             oss << first;
573             if (last > first)
574                 oss << '-' << last;
575 
576             first = last + 2;
577         }
578 
579         oss << '\n';
580     }
581 
582     *data = (string) CNcbiOstrstreamToString(oss);
583     return true;
584 }
585 
SetAllWindowTitles(void) const586 void Messenger::SetAllWindowTitles(void) const
587 {
588     SequenceViewerList::const_iterator q, qe = sequenceViewers.end();
589     for (q=sequenceViewers.begin(); q!=qe; ++q)
590         (*q)->SetWindowTitle();
591     if (structureWindow) structureWindow->SetWindowTitle();
592 }
593 
IsFileMessengerActive(void) const594 bool Messenger::IsFileMessengerActive(void) const
595 {
596     return (structureWindow && structureWindow->IsFileMessengerActive());
597 }
598 
FileMessengerSend(const std::string & toApp,const std::string & command,const std::string & data)599 void Messenger::FileMessengerSend(const std::string& toApp,
600     const std::string& command, const std::string& data)
601 {
602     if (structureWindow) structureWindow->SendCommand(toApp, command, data);
603 }
604 
605 END_SCOPE(Cn3D)
606