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