1 /*  $Id: show_hide_manager.cpp 591063 2019-08-09 15:27:34Z wangjiy $
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 *      manager object to track show/hide status of objects at various levels
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistd.hpp>
36 
37 #include "remove_header_conflicts.hpp"
38 
39 #include "show_hide_manager.hpp"
40 #include "structure_set.hpp"
41 #include "molecule.hpp"
42 #include "residue.hpp"
43 #include "chemical_graph.hpp"
44 #include "messenger.hpp"
45 #include "alignment_manager.hpp"
46 #include "opengl_renderer.hpp"
47 #include "cn3d_tools.hpp"
48 #include "molecule_identifier.hpp"
49 
50 #include <corelib/ncbistre.hpp>
51 #include <vector>
52 
53 USING_NCBI_SCOPE;
54 
55 
56 BEGIN_SCOPE(Cn3D)
57 
58 
59 // ShowHideInfo is a generic container class to help organize the list of things that can be
60 // shown/hidden; stuff derived from it allows various types of objects to be shown/hidden
61 
62 string indent("     ");
63 
64 class ShowHideInfo
65 {
66 protected:
67     string label;
68 public:
~ShowHideInfo(void)69     virtual ~ShowHideInfo(void) { }
70     vector < int > parentIndexes;
GetLabel(string * str) const71     void GetLabel(string *str) const { *str = label; }
72     virtual bool IsVisible(const ShowHideManager *shm) const = 0;
73     virtual void Show(ShowHideManager *shm, bool isShown) const = 0;
74 };
75 
76 class ShowHideObject : public ShowHideInfo
77 {
78 private:
79     const StructureObject *object;
80 public:
ShowHideObject(const StructureObject * o)81     ShowHideObject(const StructureObject *o) : object(o) { label = o->GetPDBID(); }
~ShowHideObject(void)82     virtual ~ShowHideObject(void) { }
IsVisible(const ShowHideManager * shm) const83     bool IsVisible(const ShowHideManager *shm) const { return shm->IsVisible(object); }
Show(ShowHideManager * shm,bool isShown) const84     void Show(ShowHideManager *shm, bool isShown) const { shm->Show(object, isShown); }
85 };
86 
87 class ShowHideMolecule : public ShowHideInfo
88 {
89 private:
90     const Molecule *molecule;
91 public:
ShowHideMolecule(const Molecule * m)92     ShowHideMolecule(const Molecule *m) : molecule(m)
93     {
94         label = indent + m->identifier->pdbID;
95 
96 		#ifdef _STRUCTURE_USE_LONG_PDB_CHAINS_
97 			if (m->identifier->pdbChain != " ") {
98 				label += '_';
99 				label += m->identifier->pdbChain;
100 			}
101 		#else
102 			if (m->identifier->pdbChain != ' ') {
103 				label += '_';
104 				label += (char) m->identifier->pdbChain;
105 			}
106 		#endif
107     }
~ShowHideMolecule(void)108     virtual ~ShowHideMolecule(void) { }
IsVisible(const ShowHideManager * shm) const109     bool IsVisible(const ShowHideManager *shm) const { return shm->IsVisible(molecule); }
Show(ShowHideManager * shm,bool isShown) const110     void Show(ShowHideManager *shm, bool isShown) const { shm->Show(molecule, isShown); }
111 };
112 
113 class ShowHideDomain : public ShowHideInfo
114 {
115 private:
116     const Molecule *molecule;
117     int domainID;
118 public:
ShowHideDomain(const Molecule * m,int d,int labelNum)119     ShowHideDomain(const Molecule *m, int d, int labelNum) : molecule(m), domainID(d)
120     {
121         CNcbiOstrstream oss;
122         oss << indent << indent << m->identifier->pdbID;
123 
124 		#ifdef _STRUCTURE_USE_LONG_PDB_CHAINS_
125 			if (m->identifier->pdbChain != " ") oss << '_' << m->identifier->pdbChain.c_str();
126 		#else
127 			if (m->identifier->pdbChain != ' ') oss << '_' << (char) m->identifier->pdbChain;
128 		#endif
129 
130         oss << " d" << labelNum;
131         label = (string) CNcbiOstrstreamToString(oss);
132     }
~ShowHideDomain(void)133     virtual ~ShowHideDomain(void) { }
IsVisible(const ShowHideManager * shm) const134     bool IsVisible(const ShowHideManager *shm) const
135     {
136         bool isVisible = false;
137         for (unsigned int i=0; i<molecule->NResidues(); ++i) {
138             if (molecule->residueDomains[i] == domainID &&
139                 shm->IsVisible(molecule->residues.find(i+1)->second)) {
140                 isVisible = true;   // return true if any residue from this domain is visible
141                 break;
142             }
143         }
144         return isVisible;
145     }
Show(ShowHideManager * shm,bool isShown) const146     void Show(ShowHideManager *shm, bool isShown) const
147     {
148         for (unsigned int i=0; i<molecule->NResidues(); ++i)
149             if (molecule->residueDomains[i] == domainID)
150                 shm->Show(molecule->residues.find(i+1)->second, isShown);
151     }
152 };
153 
154 
155 ///// the ShowHideManager class /////
156 
~ShowHideManager()157 ShowHideManager::~ShowHideManager()
158 {
159     for (unsigned int i=0; i<structureInfo.size(); ++i) delete structureInfo[i];
160 }
161 
PostRedrawEntity(const StructureObject * object,const Molecule * molecule,const Residue * residue)162 static void PostRedrawEntity(const StructureObject *object, const Molecule *molecule, const Residue *residue)
163 {
164     if (residue) {
165         const Molecule *m;
166         if (residue->GetParentOfType(&m))
167             GlobalMessenger()->PostRedrawMolecule(m);
168     }
169 
170     else if (molecule) {
171         GlobalMessenger()->PostRedrawMolecule(molecule);
172     }
173 
174     else if (object) {
175         // redraw all prot/nuc molecules
176         ChemicalGraph::MoleculeMap::const_iterator m, me = object->graph->molecules.end();
177         for (m=object->graph->molecules.begin(); m!=me; ++m) {
178             if (m->second->IsProtein() || m->second->IsNucleotide())
179                 GlobalMessenger()->PostRedrawMolecule(m->second);
180         }
181     }
182 
183     GlobalMessenger()->PostRedrawAllSequenceViewers();
184 }
185 
Show(const StructureBase * entity,bool isShown)186 void ShowHideManager::Show(const StructureBase *entity, bool isShown)
187 {
188     // make sure this is a valid entity
189     const StructureObject *object = dynamic_cast<const StructureObject *>(entity);
190     const Molecule *molecule = dynamic_cast<const Molecule *>(entity);
191     const Residue *residue = dynamic_cast<const Residue *>(entity);
192     if (!entity || !(object || molecule || residue)) {
193         ERRORMSG("ShowHideManager::Show() - must be a StructureObject, Molecule, or Residue");
194         return;
195     }
196 
197     EntitiesHidden::iterator e = entitiesHidden.find(entity);
198 
199     // hide an entity that's not already hidden
200     if (!isShown && e == entitiesHidden.end()) {
201         entitiesHidden[entity] = true;
202         PostRedrawEntity(object, molecule, residue);
203         entity->parentSet->renderer->ShowAllFrames();
204     }
205 
206     // show an entity that's currently hidden
207     else if (isShown && e != entitiesHidden.end()) {
208         UnHideEntityAndChildren(entity);
209         PostRedrawEntity(object, molecule, residue);
210         entity->parentSet->renderer->ShowAllFrames();
211     }
212 }
213 
UnHideEntityAndChildren(const StructureBase * entity)214 void ShowHideManager::UnHideEntityAndChildren(const StructureBase *entity)
215 {
216     if (!entity || !IsHidden(entity)) return;
217     const StructureObject *object = dynamic_cast<const StructureObject *>(entity);
218     const Molecule *molecule = dynamic_cast<const Molecule *>(entity);
219     const Residue *residue = dynamic_cast<const Residue *>(entity);
220 
221     // if entity is residue, just remove it from the list if present
222     if (residue) {
223         EntitiesHidden::iterator h = entitiesHidden.find(residue);
224         if (h != entitiesHidden.end()) entitiesHidden.erase(h);
225         return;
226     }
227 
228     // otherwise, make sure entity and its descendents are visible
229     // if it isn't already visible, then unhide this entity and all of its children
230     EntitiesHidden::iterator h, he = entitiesHidden.end();
231     for (h=entitiesHidden.begin(); h!=he; ) {
232 
233         const StructureObject *hObj = dynamic_cast<const StructureObject *>(h->first);
234         if (object && !hObj)
235             h->first->GetParentOfType(&hObj);
236         const Molecule *hMol = dynamic_cast<const Molecule *>(h->first);
237         if (molecule && hObj != h->first && !hMol)  // if not StructureObject or Molecule
238             h->first->GetParentOfType(&hMol);       // must be residue
239 
240         if (entity == h->first ||               // unhide the entity itself
241             (object && hObj == object) ||       // unhide children of a StructureObject
242             (molecule && hMol == molecule))     // unhide children of a Molecule
243         {
244             EntitiesHidden::iterator d(h);
245             ++h;
246             entitiesHidden.erase(d);
247         } else {
248             ++h;
249         }
250     }
251     PostRedrawEntity(object, molecule, residue);
252     entity->parentSet->renderer->ShowAllFrames();
253 }
254 
IsHidden(const StructureBase * entity) const255 bool ShowHideManager::IsHidden(const StructureBase *entity) const
256 {
257     if (entitiesHidden.size() == 0) return false;
258 
259     const StructureObject *object;
260     const Molecule *molecule;
261     const Residue *residue;
262 
263     EntitiesHidden::const_iterator e = entitiesHidden.find(entity);
264 
265     if ((object = dynamic_cast<const StructureObject *>(entity)) != NULL) {
266         return (e != entitiesHidden.end());
267     }
268 
269     else if ((molecule = dynamic_cast<const Molecule *>(entity)) != NULL) {
270         if (!molecule->GetParentOfType(&object)) return false;
271         return (entitiesHidden.find(object) != entitiesHidden.end() ||
272                 e != entitiesHidden.end());
273     }
274 
275     else if ((residue = dynamic_cast<const Residue *>(entity)) != NULL) {
276         if (!residue->GetParentOfType(&molecule) ||
277             !molecule->GetParentOfType(&object)) return false;
278         return (entitiesHidden.find(object) != entitiesHidden.end() ||
279                 entitiesHidden.find(molecule) != entitiesHidden.end() ||
280                 e != entitiesHidden.end());
281     }
282 
283     ERRORMSG("ShowHideManager::IsHidden() - must be a StructureObject, Molecule, or Residue");
284     return false;
285 }
286 
ConstructShowHideArray(const StructureSet * structureSet)287 void ShowHideManager::ConstructShowHideArray(const StructureSet *structureSet)
288 {
289     ShowHideInfo *info;
290     int objectIndex, moleculeIndex;
291 
292     StructureSet::ObjectList::const_iterator o, oe = structureSet->objects.end();
293     for (o=structureSet->objects.begin(); o!=oe; ++o) {
294 
295         objectIndex = structureInfo.size();
296         structureInfo.push_back(new ShowHideObject(*o));
297 
298         // list interesting (prot/nuc) chains
299         ChemicalGraph::MoleculeMap::const_iterator m, me = (*o)->graph->molecules.end();
300         for (m=(*o)->graph->molecules.begin(); m!=me; ++m) {
301             int nDom = 1; // # domains in this chain
302 
303             if (m->second->IsProtein() || m->second->IsNucleotide()) {
304                 moleculeIndex = structureInfo.size();
305                 info = new ShowHideMolecule(m->second);
306                 info->parentIndexes.push_back(objectIndex);
307                 structureInfo.push_back(info);
308 
309                 // if there at least one domain, enumerate them
310                 if (m->second->nDomains >= 1) {
311                     StructureObject::DomainMap::const_iterator d, de = (*o)->domainMap.end();
312                     for (d=(*o)->domainMap.begin(); d!=de; ++d) {
313                         if (d->second == m->second) {
314                             info = new ShowHideDomain(m->second, d->first, nDom++);
315                             info->parentIndexes.push_back(objectIndex);
316                             info->parentIndexes.push_back(moleculeIndex);
317                             structureInfo.push_back(info);
318                         }
319                     }
320                 }
321             }
322         }
323     }
324 }
325 
GetShowHideInfo(vector<string> * names,vector<bool> * visibilities) const326 void ShowHideManager::GetShowHideInfo(
327     vector < string > *names, vector < bool > *visibilities) const
328 {
329     names->resize(structureInfo.size());
330     visibilities->resize(structureInfo.size());
331     for (unsigned int i=0; i<structureInfo.size(); ++i) {
332         structureInfo[i]->GetLabel(&((*names)[i]));
333         (*visibilities)[i] = structureInfo[i]->IsVisible(this);
334     }
335 }
336 
ShowHideCallbackFunction(const vector<bool> & itemsEnabled)337 void ShowHideManager::ShowHideCallbackFunction(const vector < bool >& itemsEnabled)
338 {
339     if (itemsEnabled.size() != structureInfo.size()) {
340         ERRORMSG("ShowHideManager::ShowHideCallbackFunction() - wrong size list");
341         return;
342     }
343 
344     for (unsigned int i=0; i<itemsEnabled.size(); ++i)
345         structureInfo[i]->Show(this, itemsEnabled[i]);
346     TRACEMSG("entities hidden: " << entitiesHidden.size());
347 }
348 
SelectionChangedCallback(const vector<bool> & original,vector<bool> & itemsEnabled)349 bool ShowHideManager::SelectionChangedCallback(
350     const vector < bool >& original, vector < bool >& itemsEnabled)
351 {
352     // count number of changes
353     unsigned int i, nChanges = 0, itemChanged = 0, nEnabled = 0, itemEnabled = 0;
354     for (i=0; i<itemsEnabled.size(); ++i) {
355         if (itemsEnabled[i] != original[i]) {
356             ++nChanges;
357             itemChanged = i;
358         }
359         if (itemsEnabled[i]) {
360             ++nEnabled;
361             itemEnabled = i;
362         }
363     }
364 
365     // if change was a single de/selection, then turn off/on the children of that item
366     bool anyChange = false;
367     if (nChanges == 1 || nEnabled == 1) {
368         int item = (nChanges == 1) ? itemChanged : itemEnabled;
369         for (i=item+1; i<structureInfo.size(); ++i) {
370             for (unsigned int j=0; j<structureInfo[i]->parentIndexes.size(); ++j) {
371                 if (structureInfo[i]->parentIndexes[j] == item) {
372                     if (itemsEnabled[i] != itemsEnabled[item]) {
373                         itemsEnabled[i] = itemsEnabled[item];
374                         anyChange = true;
375                     }
376                 }
377             }
378         }
379     }
380 
381     // check all items to make sure that when an object is on, its parents are also on
382     for (i=0; i<itemsEnabled.size(); ++i) {
383         if (itemsEnabled[i]) {
384             for (unsigned int j=0; j<structureInfo[i]->parentIndexes.size(); ++j) {
385                 if (!itemsEnabled[structureInfo[i]->parentIndexes[j]]) {
386                     itemsEnabled[structureInfo[i]->parentIndexes[j]] = true;
387                     anyChange = true;
388                 }
389             }
390         }
391     }
392 
393     return anyChange;
394 }
395 
MakeAllVisible(void)396 void ShowHideManager::MakeAllVisible(void)
397 {
398     while (entitiesHidden.size() > 0) Show(entitiesHidden.begin()->first, true);
399 }
400 
ShowAlignedDomains(const StructureSet * set)401 void ShowHideManager::ShowAlignedDomains(const StructureSet *set)
402 {
403     MakeAllVisible();
404     StructureSet::ObjectList::const_iterator o, oe = set->objects.end();
405     for (o=set->objects.begin(); o!=oe; ++o) {
406         ChemicalGraph::MoleculeMap::const_iterator m, me = (*o)->graph->molecules.end();
407         for (m=(*o)->graph->molecules.begin(); m!=me; ++m) {
408 
409             if (m->second->IsNucleotide()) {        // hide all nucleotides
410                 Show(m->second, false);
411                 continue;
412             }
413 
414             if (!m->second->IsProtein()) continue;  // but leave all hets/solvents visible
415 
416             if (!set->alignmentManager->IsInAlignment(m->second->sequence)) {
417                 Show(m->second, false);
418                 continue;
419             }
420 
421             map < int, bool > domains;
422             Molecule::ResidueMap::const_iterator r, re = m->second->residues.end();
423 
424             // first pass determines which domains have any aligned residues
425             for (r=m->second->residues.begin(); r!=re; ++r)
426                 if (set->alignmentManager->IsAligned(m->second->sequence, r->first - 1))
427                     domains[m->second->residueDomains[r->first - 1]] = true;
428 
429             // second pass does hides domains not represented
430             for (r=m->second->residues.begin(); r!=re; ++r)
431                 if (domains.find(m->second->residueDomains[r->first - 1]) == domains.end())
432                     Show(r->second, false);
433         }
434     }
435 }
436 
ShowAlignedOrAnnotatedDomains(const StructureSet * set)437 void ShowHideManager::ShowAlignedOrAnnotatedDomains(const StructureSet *set)
438 {
439     MakeAllVisible();
440     StructureSet::ObjectList::const_iterator o, oe = set->objects.end();
441     for (o=set->objects.begin(); o!=oe; ++o) {
442         ChemicalGraph::MoleculeMap::const_iterator m, me = (*o)->graph->molecules.end();
443         for (m=(*o)->graph->molecules.begin(); m!=me; ++m) {
444 
445             if (!(m->second->IsProtein() || m->second->IsNucleotide()))
446                 continue;  // but leave all hets/solvents visible
447 
448             if (!(set->alignmentManager->IsInAlignment(m->second->sequence) || set->styleManager->MoleculeHasUserStyle(*o, m->second->id))) {
449                 Show(m->second, false);
450                 continue;
451             }
452 
453             map < int, bool > domains;
454             Molecule::ResidueMap::const_iterator r, re = m->second->residues.end();
455 
456             // first pass determines which domains have any aligned or annotated residues
457             for (r=m->second->residues.begin(); r!=re; ++r)
458                 if (set->alignmentManager->IsAligned(m->second->sequence, r->first - 1) || set->styleManager->ResidueHasUserStyle(*o, m->second->id, r->first))
459                     domains[m->second->residueDomains[r->first - 1]] = true;
460 
461             // second pass does hides domains not represented
462             for (r=m->second->residues.begin(); r!=re; ++r)
463                 if (domains.find(m->second->residueDomains[r->first - 1]) == domains.end())
464                     Show(r->second, false);
465         }
466     }
467 }
468 
ShowAlignedChains(const StructureSet * set)469 void ShowHideManager::ShowAlignedChains(const StructureSet *set)
470 {
471     MakeAllVisible();
472     StructureSet::ObjectList::const_iterator o, oe = set->objects.end();
473     for (o=set->objects.begin(); o!=oe; ++o) {
474         ChemicalGraph::MoleculeMap::const_iterator m, me = (*o)->graph->molecules.end();
475         for (m=(*o)->graph->molecules.begin(); m!=me; ++m) {
476 
477             // hide all nucleotides but leave all aligned proteins + hets/solvents visible
478             if (m->second->IsNucleotide() ||
479                 (m->second->IsProtein() && !set->alignmentManager->IsInAlignment(m->second->sequence)))
480             {
481                 Show(m->second, false);
482             }
483         }
484     }
485 }
486 
PrivateShowResidues(const StructureSet * set,bool showAligned)487 void ShowHideManager::PrivateShowResidues(const StructureSet *set, bool showAligned)
488 {
489     StructureSet::ObjectList::const_iterator o, oe = set->objects.end();
490     for (o=set->objects.begin(); o!=oe; ++o) {
491         ChemicalGraph::MoleculeMap::const_iterator m, me = (*o)->graph->molecules.end();
492         for (m=(*o)->graph->molecules.begin(); m!=me; ++m) {
493 
494             if (m->second->IsNucleotide()) {        // hide all nucleotides
495                 Show(m->second, false);
496                 continue;
497             }
498             if (!m->second->IsProtein()) continue;  // but leave all hets/solvents visible
499 
500             if (!set->alignmentManager->IsInAlignment(m->second->sequence)) {
501                 if (showAligned) Show(m->second, false);
502                 continue;
503             }
504 
505             Molecule::ResidueMap::const_iterator r, re = m->second->residues.end();
506             for (r=m->second->residues.begin(); r!=re; ++r) {
507                 bool aligned = set->alignmentManager->IsAligned(m->second->sequence, r->first - 1);
508                 if ((showAligned && !aligned) || (!showAligned && aligned))
509                     Show(r->second, false);
510             }
511         }
512     }
513 }
514 
ShowResidues(const StructureSet * set,bool showAligned)515 void ShowHideManager::ShowResidues(const StructureSet *set, bool showAligned)
516 {
517     MakeAllVisible();
518     PrivateShowResidues(set, showAligned);
519 }
520 
ShowUnalignedResiduesInAlignedDomains(const StructureSet * set)521 void ShowHideManager::ShowUnalignedResiduesInAlignedDomains(const StructureSet *set)
522 {
523     ShowAlignedDomains(set);
524     PrivateShowResidues(set, false);
525 }
526 
ShowSelectedResidues(const StructureSet * set)527 void ShowHideManager::ShowSelectedResidues(const StructureSet *set)
528 {
529     MakeAllVisible();
530     if (!GlobalMessenger()->IsAnythingHighlighted()) return;
531 
532     StructureSet::ObjectList::const_iterator o, oe = set->objects.end();
533     for (o=set->objects.begin(); o!=oe; ++o) {
534         bool anyResidueInObjectVisible = false;
535         ChemicalGraph::MoleculeMap::const_iterator m, me = (*o)->graph->molecules.end();
536         for (m=(*o)->graph->molecules.begin(); m!=me; ++m) {
537             Molecule::ResidueMap::const_iterator r, re = m->second->residues.end();
538             bool anyResidueInMoleculeVisible = false;
539             for (r=m->second->residues.begin(); r!=re; ++r) {
540                 if (!GlobalMessenger()->IsHighlighted(m->second, r->first))
541                     Show(r->second, false);
542                 else
543                     anyResidueInMoleculeVisible = anyResidueInObjectVisible = true;
544             }
545             if (!anyResidueInMoleculeVisible) {
546                 for (r=m->second->residues.begin(); r!=re; ++r)
547                     Show(r->second, true);  // un-flag individual residues
548                 Show(m->second, false);     // flag whole molecule as hidden
549             }
550         }
551         if (!anyResidueInObjectVisible) {
552             for (m=(*o)->graph->molecules.begin(); m!=me; ++m)
553                 Show(m->second, true);      // un-flag individual molecules
554             Show(*o, false);                // flag whole object as hidden
555         }
556     }
557 }
558 
ShowDomainsWithHighlights(const StructureSet * set)559 void ShowHideManager::ShowDomainsWithHighlights(const StructureSet *set)
560 {
561     // first, show all highlighted stuff
562     MakeAllVisible();
563     if (!GlobalMessenger()->IsAnythingHighlighted()) return;
564     ShowSelectedResidues(set);
565 
566     // then, also show all domains that contain highlighted residues
567     StructureSet::ObjectList::const_iterator o, oe = set->objects.end();
568     for (o=set->objects.begin(); o!=oe; ++o) {
569         ChemicalGraph::MoleculeMap::const_iterator m, me = (*o)->graph->molecules.end();
570         for (m=(*o)->graph->molecules.begin(); m!=me; ++m) {
571             Molecule::ResidueMap::const_iterator r, re = m->second->residues.end();
572 
573             // find domains in this molecule that have highlights
574             map < int , bool > domains;
575             int domain;
576             for (r=m->second->residues.begin(); r!=re; ++r) {
577                 if (GlobalMessenger()->IsHighlighted(m->second, r->first)) {
578                     domain = m->second->residueDomains[r->first - 1];
579                     if (domain != Molecule::NO_DOMAIN_SET)
580                         domains[domain] = true;
581                 }
582             }
583 
584             // now show all residues in these domains
585             for (r=m->second->residues.begin(); r!=re; ++r) {
586                 domain = m->second->residueDomains[r->first - 1];
587                 if (domain != Molecule::NO_DOMAIN_SET && domains.find(domain) != domains.end())
588                     Show(r->second, true);
589             }
590         }
591     }
592 }
593 
594 END_SCOPE(Cn3D)
595