style_manager.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:76k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: style_manager.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:29:44  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.84
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: style_manager.cpp,v 1000.2 2004/06/01 18:29:44 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Authors:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      manager object to track drawing style of objects at various levels
  38. *
  39. * ===========================================================================
  40. */
  41. #ifdef _MSC_VER
  42. #pragma warning(disable:4018)   // disable signed/unsigned mismatch warning in MSVC
  43. #endif
  44. #include <ncbi_pch.hpp>
  45. #include <corelib/ncbistd.hpp>
  46. #include <corelib/ncbiobj.hpp>
  47. #include <objects/cn3d/Cn3d_backbone_style.hpp>
  48. #include <objects/cn3d/Cn3d_general_style.hpp>
  49. #include <objects/cn3d/Cn3d_backbone_label_style.hpp>
  50. #include <objects/cn3d/Cn3d_color.hpp>
  51. #include <objects/cn3d/Cn3d_style_table_item.hpp>
  52. #include <objects/cn3d/Cn3d_style_table_id.hpp>
  53. #include <objects/cn3d/Cn3d_user_annotation.hpp>
  54. #include <objects/cn3d/Cn3d_object_location.hpp>
  55. #include <objects/mmdb1/Biostruc_id.hpp>
  56. #include <objects/mmdb1/Mmdb_id.hpp>
  57. #include <objects/cn3d/Cn3d_molecule_location.hpp>
  58. #include <objects/cn3d/Cn3d_residue_range.hpp>
  59. #include <objects/mmdb1/Residue_id.hpp>
  60. #include <objects/mmdb1/Molecule_id.hpp>
  61. #include <memory>
  62. #include <string.h> // for memcpy()
  63. #include "style_manager.hpp"
  64. #include "structure_set.hpp"
  65. #include "chemical_graph.hpp"
  66. #include "residue.hpp"
  67. #include "periodic_table.hpp"
  68. #include "bond.hpp"
  69. #include "show_hide_manager.hpp"
  70. #include "object_3d.hpp"
  71. #include "alignment_manager.hpp"
  72. #include "messenger.hpp"
  73. #include "cn3d_colors.hpp"
  74. #include "style_dialog.hpp"
  75. #include "annotate_dialog.hpp"
  76. #include "molecule_identifier.hpp"
  77. #include "atom_set.hpp"
  78. #include "cn3d_tools.hpp"
  79. USING_NCBI_SCOPE;
  80. USING_SCOPE(objects);
  81. BEGIN_SCOPE(Cn3D)
  82. ///// StyleSettings stuff /////
  83. static void Vector2ASNColor(const Vector &vec, CCn3d_color *asnColor)
  84. {
  85.     static const int SCALE = 10000;
  86.     asnColor->SetScale_factor(SCALE);
  87.     asnColor->SetRed((int) (vec[0] * SCALE));
  88.     asnColor->SetGreen((int) (vec[1] * SCALE));
  89.     asnColor->SetBlue((int) (vec[2] * SCALE));
  90.     asnColor->SetAlpha(SCALE);  // no alpha in Cn3D's colors
  91. }
  92. static bool SaveBackboneStyleToASN(
  93.     const StyleSettings::BackboneStyle bbSettings, CCn3d_backbone_style *bbASN)
  94. {
  95.     // these casts rely on correspondence of enumerated values!
  96.     bbASN->SetType((ECn3d_backbone_type) bbSettings.type);
  97.     bbASN->SetStyle((ECn3d_drawing_style) bbSettings.style);
  98.     bbASN->SetColor_scheme((ECn3d_color_scheme) bbSettings.colorScheme);
  99.     Vector2ASNColor(bbSettings.userColor, &(bbASN->SetUser_color()));
  100.     return true;
  101. }
  102. static bool SaveGeneralStyleToASN(
  103.     const StyleSettings::GeneralStyle gSettings, CCn3d_general_style *gASN)
  104. {
  105.     // these casts rely on correspondence of enumerated values!
  106.     gASN->SetIs_on(gSettings.isOn);
  107.     gASN->SetStyle((ECn3d_drawing_style) gSettings.style);
  108.     gASN->SetColor_scheme((ECn3d_color_scheme) gSettings.colorScheme);
  109.     Vector2ASNColor(gSettings.userColor, &(gASN->SetUser_color()));
  110.     return true;
  111. }
  112. static bool SaveLabelStyleToASN(
  113.     const StyleSettings::LabelStyle lSettings, CCn3d_backbone_label_style *lASN)
  114. {
  115.     lASN->SetSpacing(lSettings.spacing);
  116.     // these casts rely on correspondence of enumerated values!
  117.     lASN->SetType((CCn3d_backbone_label_style::EType) lSettings.type);
  118.     lASN->SetNumber((CCn3d_backbone_label_style::ENumber) lSettings.numbering);
  119.     lASN->SetTermini(lSettings.terminiOn);
  120.     lASN->SetWhite(lSettings.white);
  121.     return true;
  122. }
  123. bool StyleSettings::SaveSettingsToASN(CCn3d_style_settings *styleASN) const
  124. {
  125.     styleASN->SetVirtual_disulfides_on(virtualDisulfidesOn);
  126.     Vector2ASNColor(virtualDisulfideColor, &(styleASN->SetVirtual_disulfide_color()));
  127.     styleASN->SetHydrogens_on(hydrogensOn);
  128.     Vector2ASNColor(backgroundColor, &(styleASN->SetBackground_color()));
  129.     styleASN->SetIon_labels(ionLabelsOn);
  130.     static const int SCALE = 10000;
  131.     styleASN->SetScale_factor(SCALE);
  132.     styleASN->SetSpace_fill_proportion((int) (spaceFillProportion * SCALE));
  133.     styleASN->SetBall_radius((int) (ballRadius * SCALE));
  134.     styleASN->SetStick_radius((int) (stickRadius * SCALE));
  135.     styleASN->SetTube_radius((int) (tubeRadius * SCALE));
  136.     styleASN->SetTube_worm_radius((int) (tubeWormRadius * SCALE));
  137.     styleASN->SetHelix_radius((int) (helixRadius * SCALE));
  138.     styleASN->SetStrand_width((int) (strandWidth * SCALE));
  139.     styleASN->SetStrand_thickness((int) (strandThickness * SCALE));
  140.     return (
  141.         SaveBackboneStyleToASN(proteinBackbone, &(styleASN->SetProtein_backbone())) &&
  142.         SaveBackboneStyleToASN(nucleotideBackbone, &(styleASN->SetNucleotide_backbone())) &&
  143.         SaveGeneralStyleToASN(proteinSidechains, &(styleASN->SetProtein_sidechains())) &&
  144.         SaveGeneralStyleToASN(nucleotideSidechains, &(styleASN->SetNucleotide_sidechains())) &&
  145.         SaveGeneralStyleToASN(heterogens, &(styleASN->SetHeterogens())) &&
  146.         SaveGeneralStyleToASN(solvents, &(styleASN->SetSolvents())) &&
  147.         SaveGeneralStyleToASN(connections, &(styleASN->SetConnections())) &&
  148.         SaveGeneralStyleToASN(helixObjects, &(styleASN->SetHelix_objects())) &&
  149.         SaveGeneralStyleToASN(strandObjects, &(styleASN->SetStrand_objects())) &&
  150.         SaveLabelStyleToASN(proteinLabels, &(styleASN->SetProtein_labels())) &&
  151.         SaveLabelStyleToASN(nucleotideLabels, &(styleASN->SetNucleotide_labels()))
  152.     );
  153. }
  154. static void ASNColor2Vector(const CCn3d_color& asnColor, Vector *vec)
  155. {
  156.     int SCALE = asnColor.GetScale_factor();
  157.     vec->Set(
  158.         1.0 * asnColor.GetRed() / SCALE,
  159.         1.0 * asnColor.GetGreen() / SCALE,
  160.         1.0 * asnColor.GetBlue() / SCALE
  161.     );
  162.     // no alpha in Cn3D's colors
  163. }
  164. static bool LoadBackboneStyleFromASN(
  165.     const CCn3d_backbone_style& bbASN, StyleSettings::BackboneStyle *bbSettings)
  166. {
  167.     // these casts rely on correspondence of enumerated values!
  168.     bbSettings->type = (StyleSettings::eBackboneType) bbASN.GetType();
  169.     bbSettings->style = (StyleSettings::eDrawingStyle) bbASN.GetStyle();
  170.     bbSettings->colorScheme = (StyleSettings::eColorScheme) bbASN.GetColor_scheme();
  171.     ASNColor2Vector(bbASN.GetUser_color(), &(bbSettings->userColor));
  172.     return true;
  173. }
  174. static bool LoadGeneralStyleFromASN(
  175.     const CCn3d_general_style& gASN, StyleSettings::GeneralStyle *gSettings)
  176. {
  177.     // these casts rely on correspondence of enumerated values!
  178.     gSettings->isOn = gASN.GetIs_on();
  179.     gSettings->style = (StyleSettings::eDrawingStyle) gASN.GetStyle();
  180.     gSettings->colorScheme = (StyleSettings::eColorScheme) gASN.GetColor_scheme();
  181.     ASNColor2Vector(gASN.GetUser_color(), &(gSettings->userColor));
  182.     return true;
  183. }
  184. static bool LoadLabelStyleFromASN(
  185.     const CCn3d_backbone_label_style& lASN, StyleSettings::LabelStyle *lSettings)
  186. {
  187.     lSettings->spacing = lASN.GetSpacing();
  188.     // these casts rely on correspondence of enumerated values!
  189.     lSettings->type = (StyleSettings::eLabelType) lASN.GetType();
  190.     lSettings->numbering = (StyleSettings::eNumberType) lASN.GetNumber();
  191.     lSettings->terminiOn = lASN.GetTermini();
  192.     lSettings->white = lASN.GetWhite();
  193.     return true;
  194. }
  195. static void SetDefaultLabelStyle(StyleSettings::LabelStyle *lStyle)
  196. {
  197.     lStyle->spacing = 0;
  198.     lStyle->type = StyleSettings::eThreeLetter;
  199.     lStyle->numbering = StyleSettings::eSequentialNumbering;
  200.     lStyle->terminiOn = false;
  201.     lStyle->white = true;
  202. }
  203. bool StyleSettings::LoadSettingsFromASN(const CCn3d_style_settings& styleASN)
  204. {
  205.     virtualDisulfidesOn = styleASN.GetVirtual_disulfides_on();
  206.     ASNColor2Vector(styleASN.GetVirtual_disulfide_color(), &virtualDisulfideColor);
  207.     hydrogensOn = styleASN.GetHydrogens_on();
  208.     ASNColor2Vector(styleASN.GetBackground_color(), &backgroundColor);
  209.     int SCALE = styleASN.GetScale_factor();
  210.     spaceFillProportion = 1.0 * styleASN.GetSpace_fill_proportion() / SCALE;
  211.     stickRadius = 1.0 * styleASN.GetStick_radius() / SCALE;
  212.     tubeRadius = 1.0 * styleASN.GetTube_radius() / SCALE;
  213.     tubeWormRadius = 1.0 * styleASN.GetTube_worm_radius() / SCALE;
  214.     helixRadius = 1.0 * styleASN.GetHelix_radius() / SCALE;
  215.     strandWidth = 1.0 * styleASN.GetStrand_width() / SCALE;
  216.     strandThickness = 1.0 * styleASN.GetStrand_thickness() / SCALE;
  217.     // label defaults (since they're optional in ASN spec)
  218.     if (styleASN.IsSetProtein_labels()) {
  219.         if (!LoadLabelStyleFromASN(styleASN.GetProtein_labels(), &proteinLabels)) return false;
  220.     } else
  221.         SetDefaultLabelStyle(&proteinLabels);
  222.     if (styleASN.IsSetNucleotide_labels()) {
  223.         if (!LoadLabelStyleFromASN(styleASN.GetNucleotide_labels(), &nucleotideLabels)) return false;
  224.     } else
  225.         SetDefaultLabelStyle(&nucleotideLabels);
  226.     // ion labels on by default
  227.     ionLabelsOn = (styleASN.IsSetIon_labels()) ? styleASN.GetIon_labels() : true;
  228.     return (
  229.         LoadBackboneStyleFromASN(styleASN.GetProtein_backbone(), &proteinBackbone) &&
  230.         LoadBackboneStyleFromASN(styleASN.GetNucleotide_backbone(), &nucleotideBackbone) &&
  231.         LoadGeneralStyleFromASN(styleASN.GetProtein_sidechains(), &proteinSidechains) &&
  232.         LoadGeneralStyleFromASN(styleASN.GetNucleotide_sidechains(), &nucleotideSidechains) &&
  233.         LoadGeneralStyleFromASN(styleASN.GetHeterogens(), &heterogens) &&
  234.         LoadGeneralStyleFromASN(styleASN.GetSolvents(), &solvents) &&
  235.         LoadGeneralStyleFromASN(styleASN.GetConnections(), &connections) &&
  236.         LoadGeneralStyleFromASN(styleASN.GetHelix_objects(), &helixObjects) &&
  237.         LoadGeneralStyleFromASN(styleASN.GetStrand_objects(), &strandObjects)
  238.     );
  239. }
  240. StyleSettings& StyleSettings::operator = (const StyleSettings& orig)
  241. {
  242.     memcpy(this, &orig, sizeof(StyleSettings));
  243.     return *this;
  244. }
  245. void StyleSettings::SetRenderingStyle(ePredefinedRenderingStyle style)
  246. {
  247.     // variable settings
  248.     switch (style) {
  249.         // set sidechains isOn only
  250.         case eToggleSidechainsShortcut:
  251.             proteinSidechains.isOn = !proteinSidechains.isOn;
  252.             nucleotideSidechains.isOn = !nucleotideSidechains.isOn;
  253.             return;
  254.         case eWormShortcut:
  255.             proteinBackbone.type = nucleotideBackbone.type = eTrace;
  256.             proteinBackbone.style = nucleotideBackbone.style = eTubeWorm;
  257.             proteinSidechains.isOn = nucleotideSidechains.isOn = false;
  258.             proteinSidechains.style = nucleotideSidechains.style = eWire;
  259.             heterogens.style = eBallAndStick;
  260.             solvents.isOn = false;
  261.             solvents.style = eBallAndStick;
  262.             connections.style = eTubes;
  263.             helixObjects.isOn = strandObjects.isOn = true;
  264.             helixObjects.style = strandObjects.style = eWithArrows;
  265.             break;
  266.         case eTubeShortcut:
  267.             proteinBackbone.type = nucleotideBackbone.type = eTrace;
  268.             proteinBackbone.style = nucleotideBackbone.style = eTubes;
  269.             proteinSidechains.isOn = nucleotideSidechains.isOn = false;
  270.             proteinSidechains.style = nucleotideSidechains.style = eWire;
  271.             heterogens.style = eBallAndStick;
  272.             solvents.isOn = false;
  273.             solvents.style = eBallAndStick;
  274.             connections.style = eTubes;
  275.             helixObjects.isOn = strandObjects.isOn = false;
  276.             helixObjects.style = strandObjects.style = eWithArrows;
  277.             break;
  278.         case eWireframeShortcut:
  279.             proteinBackbone.type = nucleotideBackbone.type = eComplete;
  280.             proteinBackbone.style = nucleotideBackbone.style = eWire;
  281.             proteinSidechains.isOn = nucleotideSidechains.isOn = true;
  282.             proteinSidechains.style = nucleotideSidechains.style = eWire;
  283.             heterogens.style = eWire;
  284.             solvents.isOn = false;
  285.             solvents.style = eBallAndStick;
  286.             connections.style = eWire;
  287.             helixObjects.isOn = strandObjects.isOn = false;
  288.             helixObjects.style = strandObjects.style = eWithArrows;
  289.             break;
  290.         case eBallAndStickShortcut:
  291.             proteinBackbone.type = nucleotideBackbone.type = eComplete;
  292.             proteinBackbone.style = nucleotideBackbone.style = eBallAndStick;
  293.             proteinSidechains.isOn = nucleotideSidechains.isOn = true;
  294.             proteinSidechains.style = nucleotideSidechains.style = eBallAndStick;
  295.             heterogens.style = eBallAndStick;
  296.             solvents.isOn = false;
  297.             solvents.style = eBallAndStick;
  298.             connections.style = eTubes;
  299.             helixObjects.isOn = strandObjects.isOn = false;
  300.             helixObjects.style = strandObjects.style = eWithArrows;
  301.             break;
  302.         case eSpacefillShortcut:
  303.             proteinBackbone.type = nucleotideBackbone.type = eComplete;
  304.             proteinBackbone.style = nucleotideBackbone.style = eSpaceFill;
  305.             proteinSidechains.isOn = nucleotideSidechains.isOn = true;
  306.             proteinSidechains.style = nucleotideSidechains.style = eSpaceFill;
  307.             heterogens.style = eSpaceFill;
  308.             solvents.isOn = false;
  309.             solvents.style = eSpaceFill;
  310.             connections.style = eTubes;
  311.             helixObjects.isOn = strandObjects.isOn = false;
  312.             helixObjects.style = strandObjects.style = eWithArrows;
  313.             break;
  314.     }
  315.     // common settings
  316.     heterogens.isOn = true;
  317.     connections.isOn = true;
  318.     virtualDisulfidesOn = true;
  319.     hydrogensOn = true;
  320.     helixRadius = 1.8;
  321.     strandWidth = 2.0;
  322.     strandThickness = 0.5;
  323.     spaceFillProportion = 1.0;
  324.     ballRadius = 0.4;
  325.     stickRadius = 0.2;
  326.     tubeRadius = 0.3;
  327.     tubeWormRadius = 0.3;
  328. }
  329. void StyleSettings::SetColorScheme(ePredefinedColorScheme scheme)
  330. {
  331.     // variable settings
  332.     switch (scheme) {
  333.         case eSecondaryStructureShortcut:
  334.             proteinBackbone.colorScheme = eSecondaryStructure;
  335.             nucleotideBackbone.colorScheme = eMolecule;
  336.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eElement;
  337.             heterogens.colorScheme = solvents.colorScheme = eElement;
  338.             helixObjects.colorScheme = strandObjects.colorScheme = eSecondaryStructure;
  339.             break;
  340.         case eAlignedShortcut: case eIdentityShortcut: case eVarietyShortcut:
  341.         case eWeightedVarietyShortcut: case eInformationContentShortcut:
  342.         case eFitShortcut: case eBlockFitShortcut: case eBlockZFitShortcut: case eBlockRowFitShortcut:
  343.             switch (scheme) {
  344.                 case eAlignedShortcut: proteinBackbone.colorScheme = eAligned; break;
  345.                 case eIdentityShortcut: proteinBackbone.colorScheme = eIdentity; break;
  346.                 case eVarietyShortcut: proteinBackbone.colorScheme = eVariety; break;
  347.                 case eWeightedVarietyShortcut: proteinBackbone.colorScheme = eWeightedVariety; break;
  348.                 case eInformationContentShortcut: proteinBackbone.colorScheme = eInformationContent; break;
  349.                 case eFitShortcut: proteinBackbone.colorScheme = eFit; break;
  350.                 case eBlockFitShortcut: proteinBackbone.colorScheme = eBlockFit; break;
  351.                 case eBlockZFitShortcut: proteinBackbone.colorScheme = eBlockZFit; break;
  352.                 case eBlockRowFitShortcut: proteinBackbone.colorScheme = eBlockRowFit; break;
  353.             }
  354.             nucleotideBackbone.colorScheme = eMolecule;
  355.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eElement;
  356.             heterogens.colorScheme = solvents.colorScheme = eElement;
  357.             helixObjects.colorScheme = strandObjects.colorScheme = eObject;
  358.             break;
  359.         case eObjectShortcut:
  360.             proteinBackbone.colorScheme = eObject;
  361.             nucleotideBackbone.colorScheme = eObject;
  362.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eObject;
  363.             heterogens.colorScheme = solvents.colorScheme = eObject;
  364.             helixObjects.colorScheme = strandObjects.colorScheme = eObject;
  365.             break;
  366.         case eDomainShortcut:
  367.             proteinBackbone.colorScheme = eDomain;
  368.             nucleotideBackbone.colorScheme = eDomain;
  369.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eElement;
  370.             heterogens.colorScheme = solvents.colorScheme = eElement;
  371.             helixObjects.colorScheme = strandObjects.colorScheme = eDomain;
  372.             break;
  373.         case eMoleculeShortcut:
  374.             proteinBackbone.colorScheme = eMolecule;
  375.             nucleotideBackbone.colorScheme = eMolecule;
  376.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eMolecule;
  377.             heterogens.colorScheme = solvents.colorScheme = eMolecule;
  378.             helixObjects.colorScheme = strandObjects.colorScheme = eMolecule;
  379.             break;
  380.         case eRainbowShortcut:
  381.             proteinBackbone.colorScheme = eRainbow;
  382.             nucleotideBackbone.colorScheme = eRainbow;
  383.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eRainbow;
  384.             heterogens.colorScheme = solvents.colorScheme = eElement;
  385.             helixObjects.colorScheme = strandObjects.colorScheme = eObject;
  386.             break;
  387.         case eHydrophobicityShortcut:
  388.             proteinBackbone.colorScheme = eHydrophobicity;
  389.             nucleotideBackbone.colorScheme = eMolecule;
  390.             proteinSidechains.colorScheme = eHydrophobicity;
  391.             nucleotideSidechains.colorScheme = eElement;
  392.             heterogens.colorScheme = solvents.colorScheme = eElement;
  393.             helixObjects.colorScheme = strandObjects.colorScheme = eObject;
  394.             break;
  395.         case eChargeShortcut:
  396.             proteinBackbone.colorScheme = eCharge;
  397.             nucleotideBackbone.colorScheme = eElement;
  398.             proteinSidechains.colorScheme = eCharge;
  399.             nucleotideSidechains.colorScheme = eElement;
  400.             heterogens.colorScheme = solvents.colorScheme = eElement;
  401.             helixObjects.colorScheme = strandObjects.colorScheme = eObject;
  402.             break;
  403.         case eTemperatureShortcut:
  404.             proteinBackbone.colorScheme = eTemperature;
  405.             nucleotideBackbone.colorScheme = eTemperature;
  406.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eTemperature;
  407.             heterogens.colorScheme = solvents.colorScheme = eTemperature;
  408.             helixObjects.colorScheme = strandObjects.colorScheme = eObject;
  409.             break;
  410.         case eElementShortcut:
  411.             proteinBackbone.colorScheme = eElement;
  412.             nucleotideBackbone.colorScheme = eElement;
  413.             proteinSidechains.colorScheme = nucleotideSidechains.colorScheme = eElement;
  414.             heterogens.colorScheme = eElement;
  415.             solvents.colorScheme = eElement;
  416.             helixObjects.colorScheme = strandObjects.colorScheme = eObject;
  417.             break;
  418.     }
  419.     // common settings
  420.     connections.colorScheme = eUserSelect;
  421.     connections.userColor.Set(0.9,0.9,1);
  422.     virtualDisulfideColor.Set(0.93,0.55,0.05);
  423.     backgroundColor.Set(0,0,0);
  424.     proteinSidechains.userColor = nucleotideSidechains.userColor =
  425.     proteinBackbone.userColor = nucleotideBackbone.userColor =
  426.     heterogens.userColor = solvents.userColor =
  427.     helixObjects.userColor = strandObjects.userColor = Vector(0.5,0.5,0.5);
  428. }
  429. void StyleSettings::SetDefaultLabeling(void)
  430. {
  431.     SetDefaultLabelStyle(&proteinLabels);
  432.     SetDefaultLabelStyle(&nucleotideLabels);
  433.     ionLabelsOn = true;
  434. }
  435. ///// StyleManager stuff /////
  436. StyleManager::StyleManager(const StructureSet *set) : structureSet(set)
  437. {
  438. }
  439. bool StyleManager::CheckGlobalStyleSettings()
  440. {
  441.     return CheckStyleSettings(&globalStyle);
  442. }
  443. // check for inconsistencies in style settings; returns false if there's an uncorrectable problem
  444. bool StyleManager::CheckStyleSettings(StyleSettings *settings)
  445. {
  446.     // can't do worm with partial or complete backbone
  447.     if (((settings->proteinBackbone.style == StyleSettings::eWireWorm ||
  448.           settings->proteinBackbone.style == StyleSettings::eTubeWorm) &&
  449.          (settings->proteinBackbone.type == StyleSettings::ePartial ||
  450.           settings->proteinBackbone.type == StyleSettings::eComplete))) {
  451.         settings->proteinBackbone.type = StyleSettings::eTrace;
  452.     }
  453.     if (((settings->nucleotideBackbone.style == StyleSettings::eWireWorm ||
  454.           settings->nucleotideBackbone.style == StyleSettings::eTubeWorm) &&
  455.          (settings->nucleotideBackbone.type == StyleSettings::ePartial ||
  456.           settings->nucleotideBackbone.type == StyleSettings::eComplete))) {
  457.         settings->nucleotideBackbone.type = StyleSettings::eTrace;
  458.     }
  459.     // can't do non-trace backbones for ncbi-backbone models
  460.     if (structureSet->isAlphaOnly) {
  461.         if (settings->proteinBackbone.type == StyleSettings::ePartial ||
  462.             settings->proteinBackbone.type == StyleSettings::eComplete) {
  463.             settings->proteinBackbone.type = StyleSettings::eTrace;
  464.         }
  465.         if (settings->nucleotideBackbone.type == StyleSettings::ePartial ||
  466.             settings->nucleotideBackbone.type == StyleSettings::eComplete) {
  467.             settings->nucleotideBackbone.type = StyleSettings::eTrace;
  468.         }
  469.     }
  470.     return true;
  471. }
  472. const double UNKNOWN_HYDROPHOBICITY = -1.0;
  473. // return a hydrophobicity value from [0..1]
  474. double GetHydrophobicity(char code)
  475. {
  476.     // Amino acid scale: Normalized consensus hydrophobicity scale.
  477.     // Author(s): Eisenberg D., Schwarz E., Komarony M., Wall R.
  478.     // Reference: J. Mol. Biol. 179:125-142(1984).
  479.     // Amino acid scale values: (normalized to [0..1])
  480.     switch (code) {
  481.         case 'A': return ( 0.620 + 2.530) / (1.380 + 2.530);
  482.         case 'R': return (-2.530 + 2.530) / (1.380 + 2.530);
  483.         case 'N': return (-0.780 + 2.530) / (1.380 + 2.530);
  484.         case 'D': return (-0.900 + 2.530) / (1.380 + 2.530);
  485.         case 'C': return ( 0.290 + 2.530) / (1.380 + 2.530);
  486.         case 'Q': return (-0.850 + 2.530) / (1.380 + 2.530);
  487.         case 'E': return (-0.740 + 2.530) / (1.380 + 2.530);
  488.         case 'G': return ( 0.480 + 2.530) / (1.380 + 2.530);
  489.         case 'H': return (-0.400 + 2.530) / (1.380 + 2.530);
  490.         case 'I': return ( 1.380 + 2.530) / (1.380 + 2.530);
  491.         case 'L': return ( 1.060 + 2.530) / (1.380 + 2.530);
  492.         case 'K': return (-1.500 + 2.530) / (1.380 + 2.530);
  493.         case 'M': return ( 0.640 + 2.530) / (1.380 + 2.530);
  494.         case 'F': return ( 1.190 + 2.530) / (1.380 + 2.530);
  495.         case 'P': return ( 0.120 + 2.530) / (1.380 + 2.530);
  496.         case 'S': return (-0.180 + 2.530) / (1.380 + 2.530);
  497.         case 'T': return (-0.050 + 2.530) / (1.380 + 2.530);
  498.         case 'W': return ( 0.810 + 2.530) / (1.380 + 2.530);
  499.         case 'Y': return ( 0.260 + 2.530) / (1.380 + 2.530);
  500.         case 'V': return ( 1.080 + 2.530) / (1.380 + 2.530);
  501.     }
  502.     return UNKNOWN_HYDROPHOBICITY;
  503. }
  504. int GetCharge(char code)
  505. {
  506.     switch (code) {
  507.         case 'R': case 'H': case 'K': return 1;
  508.         case 'D': case 'E': return -1;
  509.     }
  510.     return 0;
  511. }
  512. #define ATOM_NOT_DISPLAYED do { 
  513.     atomStyle->style = eNotDisplayed; 
  514.     return true; } while (0)
  515. // get display style for atom, including show/hide status.
  516. // May want to cache this eventually, since a
  517. // particular atom's style may be queried several times per render (once for
  518. // drawing atoms, and once for each bond to the atom).
  519. bool StyleManager::GetAtomStyle(const Residue *residue,
  520.     const AtomPntr& atom, const AtomCoord *coord,
  521.     AtomStyle *atomStyle,
  522.     const StyleSettings::BackboneStyle* *saveBackboneStyle,
  523.     const StyleSettings::GeneralStyle* *saveGeneralStyle) const
  524. {
  525.     if (!residue || !atomStyle) {
  526.         ERRORMSG("StyleManager::GetAtomStyle() got NULL residue or atomStyle");
  527.         return false;
  528.     }
  529.     atomStyle->isHighlighted = false; // queried sometimes even if atom not displayed
  530.     const Molecule *molecule;
  531.     if (!residue->GetParentOfType(&molecule)) return false;
  532.     const StructureObject *object;
  533.     if (!molecule->GetParentOfType(&object)) return false;
  534.     const StyleSettings& settings = GetStyleForResidue(object, atom.mID, atom.rID);
  535.     const Residue::AtomInfo *info = residue->GetAtomInfo(atom.aID);
  536.     if (!info)
  537.         ATOM_NOT_DISPLAYED;
  538.     // set up some pointers for more convenient access to style settings
  539.     const StyleSettings::BackboneStyle *backboneStyle = NULL;
  540.     const StyleSettings::GeneralStyle *generalStyle = NULL;
  541.     if (info->classification == Residue::eAlphaBackboneAtom ||
  542.         info->classification == Residue::ePartialBackboneAtom ||
  543.         info->classification == Residue::eCompleteBackboneAtom) {
  544.         if (residue->IsAminoAcid())
  545.             backboneStyle = &(settings.proteinBackbone);
  546.         else
  547.             backboneStyle = &(settings.nucleotideBackbone);
  548.     } else if (info->classification == Residue::eSideChainAtom) {
  549.         if (residue->IsAminoAcid())
  550.             generalStyle = &(settings.proteinSidechains);
  551.         else
  552.             generalStyle = &(settings.nucleotideSidechains);
  553.     } else { // Residue::eUnknownAtom
  554.         if (molecule->IsSolvent())
  555.             generalStyle = &(settings.solvents);
  556.         else if (molecule->IsHeterogen())
  557.             generalStyle = &(settings.heterogens);
  558.         else {
  559.             ERRORMSG("StyleManager::GetAtomStyle() - confused about molecule/atom classification");
  560.             return false;
  561.         }
  562.     }
  563.     if ((!backboneStyle && !generalStyle) || (backboneStyle && generalStyle)) {
  564.         ERRORMSG("StyleManager::GetAtomStyle() - confused about style settings");
  565.         return false;
  566.     }
  567.     if (saveBackboneStyle) *saveBackboneStyle = backboneStyle;
  568.     if (saveGeneralStyle) *saveGeneralStyle = generalStyle;
  569.     // first check whether this atom is visible, based on show/hide and backbone and sidechain settings
  570.     if (object->parentSet->showHideManager->IsHidden(residue))
  571.         ATOM_NOT_DISPLAYED;
  572.     if (info->atomicNumber == 1 && !settings.hydrogensOn)
  573.         ATOM_NOT_DISPLAYED;
  574.     if (info->classification == Residue::eSideChainAtom && !generalStyle->isOn)
  575.        ATOM_NOT_DISPLAYED;
  576.     if (info->classification == Residue::eAlphaBackboneAtom ||
  577.         info->classification == Residue::ePartialBackboneAtom ||
  578.         info->classification == Residue::eCompleteBackboneAtom) { // is backbone of some sort
  579.         // control presence of non CA/C1* backbone atoms
  580.         if ((residue->IsAminoAcid() && info->classification != Residue::eAlphaBackboneAtom) ||
  581.             (residue->IsNucleotide() && info->code != " C1*")) {
  582.             // skip if backbone off
  583.             if (backboneStyle->type == StyleSettings::eOff)
  584.                 ATOM_NOT_DISPLAYED;
  585.             // show only alpha atom if eTrace
  586.             if (backboneStyle->type == StyleSettings::eTrace &&
  587.                 info->classification != Residue::eAlphaBackboneAtom)
  588.                 ATOM_NOT_DISPLAYED;
  589.             // don't show complete backbone if set to partial
  590.             if (info->classification == Residue::eCompleteBackboneAtom &&
  591.                 backboneStyle->type == StyleSettings::ePartial)
  592.                 ATOM_NOT_DISPLAYED;
  593.         }
  594.         // if this is alpha/C1* and backbone is off, but sidechains are on, then
  595.         // let the atom be visible *and* take the style of the sidechain
  596.         else if (backboneStyle->type == StyleSettings::eOff ||
  597.                  (residue->IsNucleotide() && backboneStyle->type != StyleSettings::eComplete)) {
  598.             const StyleSettings::GeneralStyle *sidechainStyle = NULL;
  599.             if (residue->IsAminoAcid()) sidechainStyle = &(settings.proteinSidechains);
  600.             else if (residue->IsNucleotide()) sidechainStyle = &(settings.nucleotideSidechains);
  601.             if (sidechainStyle && sidechainStyle->isOn) {
  602.                 backboneStyle = NULL;
  603.                 generalStyle = sidechainStyle;
  604.             } else
  605.                 ATOM_NOT_DISPLAYED;
  606.         }
  607.     }
  608.     if (info->classification == Residue::eUnknownAtom && !generalStyle->isOn)
  609.         ATOM_NOT_DISPLAYED;
  610.     const Element *element = PeriodicTable.GetElement(info->atomicNumber);
  611.     // determine radius
  612.     switch (backboneStyle ? backboneStyle->style : generalStyle->style) {
  613.         case StyleSettings::eWire:
  614.         case StyleSettings::eWireWorm:
  615.         case StyleSettings::eTubeWorm:
  616.             // no atom, but don't do ATOM_NOT_DISPLAYED, because bonds to this atom
  617.             // still may be displayed and need style info about this atom
  618.             atomStyle->radius = 0.0;
  619.             break;
  620.         case StyleSettings::eTubes:
  621.             atomStyle->radius = settings.tubeRadius;
  622.             break;
  623.         case StyleSettings::eBallAndStick:
  624.             atomStyle->radius = settings.ballRadius;
  625.             break;
  626.         case StyleSettings::eSpaceFill:
  627.             atomStyle->radius = element->vdWRadius * settings.spaceFillProportion;
  628.             break;
  629.         default:
  630.             ERRORMSG("StyleManager::GetAtomStyle() - inappropriate style for atom");
  631.             return false;
  632.     }
  633.     // determine color
  634.     StyleSettings::eColorScheme
  635.         colorStyle = backboneStyle ? backboneStyle->colorScheme : generalStyle->colorScheme;
  636.     switch (colorStyle) {
  637.         case StyleSettings::eElement:
  638.             atomStyle->color = element->color;
  639.             break;
  640.         case StyleSettings::eAligned:
  641.         case StyleSettings::eIdentity:
  642.         case StyleSettings::eVariety:
  643.         case StyleSettings::eWeightedVariety:
  644.         case StyleSettings::eInformationContent:
  645.         case StyleSettings::eFit:
  646.         case StyleSettings::eBlockFit:
  647.         case StyleSettings::eBlockZFit:
  648.         case StyleSettings::eBlockRowFit:
  649.             if (molecule->sequence &&
  650.                 molecule->parentSet->alignmentManager->
  651.                     IsAligned(molecule->sequence, residue->id - 1)) { // assume seqIndex is rID - 1
  652.                 const Vector * color = molecule->parentSet->alignmentManager->
  653.                     GetAlignmentColor(molecule->sequence, residue->id - 1, colorStyle);
  654.                 if (color)
  655.                     atomStyle->color = *color;
  656.                 else
  657.                     atomStyle->color = GlobalColors()->Get(Colors::eUnaligned);
  658.                 break;
  659.             }
  660.             if (colorStyle != StyleSettings::eAligned) {
  661.                 atomStyle->color = GlobalColors()->Get(Colors::eUnaligned);
  662.                 break;
  663.             }
  664.             // if eAligned and not aligned, then fall through to use eObject coloring
  665.         case StyleSettings::eObject:
  666.             atomStyle->color = GlobalColors()->Get(Colors::eCycle1, object->id - 1);
  667.             break;
  668.         case StyleSettings::eDomain:
  669.             atomStyle->color =
  670.                 (molecule->residueDomains[residue->id - 1] == Molecule::NO_DOMAIN_SET) ?
  671.                     GlobalColors()->Get(Colors::eNoDomain) :
  672.                     GlobalColors()->Get(Colors::eCycle1, molecule->residueDomains[residue->id - 1] - 1);
  673.             break;
  674.         case StyleSettings::eMolecule:
  675.             atomStyle->color = GlobalColors()->Get(Colors::eCycle1, molecule->id - 1);
  676.             break;
  677.         case StyleSettings::eRainbow: {
  678.             double pos = 1.0;
  679.             if ((residue->IsAminoAcid() || residue->IsNucleotide()) && molecule->NResidues() > 1) {
  680.                 pos = 1.0 * (residue->id - 1) / (molecule->NResidues() - 1);
  681.             }
  682.             atomStyle->color = GlobalColors()->Get(Colors::eRainbowMap, pos);
  683.             break;
  684.         }
  685.         case StyleSettings::eSecondaryStructure:
  686.             if (molecule->IsResidueInHelix(residue->id))
  687.                 atomStyle->color = GlobalColors()->Get(Colors::eHelix);
  688.             else if (molecule->IsResidueInStrand(residue->id))
  689.                 atomStyle->color = GlobalColors()->Get(Colors::eStrand);
  690.             else
  691.                 atomStyle->color = GlobalColors()->Get(Colors::eCoil);
  692.             break;
  693.         case StyleSettings::eCharge: {
  694.             int charge = (residue->IsAminoAcid()) ? GetCharge(residue->code) : 0;
  695.             atomStyle->color = GlobalColors()->Get(
  696.                 (charge > 0) ? Colors::ePositive : ((charge < 0) ? Colors::eNegative : Colors::eNeutral));
  697.             break;
  698.         }
  699.         case StyleSettings::eTemperature:
  700.             atomStyle->color =
  701.                 (coord && coord->averageTemperature != AtomCoord::NO_TEMPERATURE &&
  702.  object->maxTemperature != object->minTemperature) ?
  703.                     GlobalColors()->Get(Colors::eTemperatureMap,
  704.                         (coord->averageTemperature - object->minTemperature) /
  705.                         (object->maxTemperature - object->minTemperature)) :
  706.                     GlobalColors()->Get(Colors::eNoTemperature);
  707.             break;
  708.         case StyleSettings::eHydrophobicity: {
  709.             double hydrophobicity = (residue->IsAminoAcid()) ?
  710.                 GetHydrophobicity(residue->code) : UNKNOWN_HYDROPHOBICITY;
  711.             atomStyle->color = (hydrophobicity != UNKNOWN_HYDROPHOBICITY) ?
  712.                 GlobalColors()->Get(Colors::eHydrophobicityMap, hydrophobicity) :
  713.                 GlobalColors()->Get(Colors::eNoHydrophobicity);
  714.             break;
  715.         }
  716.         case StyleSettings::eUserSelect:
  717.             if (backboneStyle)
  718.                 atomStyle->color = backboneStyle->userColor;
  719.             else
  720.                 atomStyle->color = generalStyle->userColor;
  721.             break;
  722.         default:
  723.             ERRORMSG("StyleManager::GetAtomStyle() - inappropriate color scheme for atom");
  724.             return false;
  725.     }
  726.     // determine transparency and metal ion labeling
  727.     atomStyle->centerLabel.erase();
  728.     if (molecule->IsSolvent())
  729.         atomStyle->style = eTransparentAtom;
  730.     else if (IsMetal(info->atomicNumber) ||
  731.              (molecule->NResidues() == 1 && residue->NAtomsInGraph() == 1)) {
  732.         atomStyle->style = eTransparentAtom;
  733.         // always big spheres for metals or isolated atoms
  734.         atomStyle->radius = element->vdWRadius * settings.spaceFillProportion;
  735.         if (settings.ionLabelsOn)
  736.             atomStyle->centerLabel = element->symbol;
  737.     } else
  738.         atomStyle->style = eSolidAtom;
  739.     // add transparency; scale by occupancy if transparent
  740.     if (atomStyle->style == eTransparentAtom) {
  741.         atomStyle->alpha = 0.6;
  742.         if (coord && coord->occupancy < 1 && coord->occupancy > 0)
  743.             atomStyle->alpha *= coord->occupancy;
  744.     } else
  745.         atomStyle->alpha = 1.0;
  746.     // determine whether it's highlighted, but *don't* set the color to the highlight
  747.     // color yet, since this is used by the sequence viewer where the residue letter is
  748.     // colored independently of the highlighted background
  749.     atomStyle->isHighlighted = GlobalMessenger()->IsHighlighted(molecule, residue->id);
  750.     atomStyle->name = info->glName;
  751.     return true;
  752. }
  753. // this is basically a map from StyleSettings enums to StyleManager enums;
  754. // sets bond radius, too
  755. static bool SetBondStyleFromResidueStyle(StyleSettings::eDrawingStyle style,
  756.     const StyleSettings& settings, BondStyle::EndStyle *end)
  757. {
  758.     switch (style) {
  759.         case StyleSettings::eWire:
  760.             end->style = StyleManager::eLineBond;
  761.             break;
  762.         case StyleSettings::eTubes:
  763.             end->style = StyleManager::eCylinderBond;
  764.             end->radius = settings.tubeRadius;
  765.             break;
  766.         case StyleSettings::eBallAndStick:
  767.             end->style = StyleManager::eCylinderBond;
  768.             end->radius = settings.stickRadius;
  769.             break;
  770.         case StyleSettings::eSpaceFill:
  771.             end->style = StyleManager::eLineBond;
  772.             break;
  773.         case StyleSettings::eWireWorm:
  774.             end->style = StyleManager::eLineWormBond;
  775.             break;
  776.         case StyleSettings::eTubeWorm:
  777.             end->style = StyleManager::eThickWormBond;
  778.             end->radius = settings.tubeWormRadius;
  779.             break;
  780.         default:
  781.             ERRORMSG("SetBondStyleFromResidueStyle() - invalid style for bond");
  782.             return false;
  783.     }
  784.     return true;
  785. }
  786. #define BOND_NOT_DISPLAYED do { 
  787.     bondStyle->end1.style = bondStyle->end2.style = eNotDisplayed; 
  788.     return true; } while (0)
  789. // Bond style is set by the residue style of the atoms at each end; the color
  790. // is taken from the atom style (GetAtomStyle()), as well as some convenience
  791. // style pointers (backboneStyle, generalStyle). Show/hide status is taken
  792. // from the atoms - if either is hidden, the bond isn't shown either.
  793. bool StyleManager::GetBondStyle(const Bond *bond,
  794.         const AtomPntr& atom1, const AtomCoord *coord1,
  795.         const AtomPntr& atom2, const AtomCoord *coord2,
  796.         double bondLength, BondStyle *bondStyle) const
  797. {
  798.     const StructureObject *object;
  799.     if (!bond->GetParentOfType(&object)) return false;
  800.     const Residue::AtomInfo
  801.         *info1 = object->graph->GetAtomInfo(atom1),
  802.         *info2 = object->graph->GetAtomInfo(atom2);
  803.     if (!info1 || !info2) BOND_NOT_DISPLAYED;
  804.     AtomStyle atomStyle1, atomStyle2;
  805.     const StyleSettings::BackboneStyle *backboneStyle1, *backboneStyle2;
  806.     const StyleSettings::GeneralStyle *generalStyle1, *generalStyle2;
  807.     if (!GetAtomStyle(info1->residue, atom1, coord1, &atomStyle1, &backboneStyle1, &generalStyle1) ||
  808.         !GetAtomStyle(info2->residue, atom2, coord2, &atomStyle2, &backboneStyle2, &generalStyle2))
  809.         return false;
  810.     // if both atoms are hidden, or either one doesn't have coordinates, don't show the bond
  811.     if ((atomStyle1.style == eNotDisplayed && atomStyle2.style == eNotDisplayed) || (!coord1 || !coord2))
  812.         BOND_NOT_DISPLAYED;
  813.      // defaults
  814.     bondStyle->end1.atomCap = bondStyle->end2.atomCap = false;
  815.     bondStyle->end1.name = info1->glName;
  816.     bondStyle->end2.name = info2->glName;
  817.     bondStyle->midCap = false;
  818.     // if one atom is hidden, check for special cases to see if bond is visible at all
  819.     if (atomStyle1.style == eNotDisplayed || atomStyle2.style == eNotDisplayed) {
  820.         bool isSpecial = false;
  821.         // is residue PRO, and bond is between CD and N?
  822.         if (info1->residue->IsAminoAcid() && info1->residue->nameGraph == "PRO" &&
  823.             atom1.mID == atom2.mID && atom1.rID == atom2.rID)
  824.         {
  825.             const Molecule *molecule;
  826.             if (!info1->residue->GetParentOfType(&molecule))
  827.                 return false;
  828.             // atom1 is CD and is visible, switch N (atom2) to side chain style
  829.             if (info1->code == " CD " && atomStyle1.style != eNotDisplayed && info2->code == " N  ")
  830.             {
  831.                 generalStyle2 = generalStyle1;
  832.                 backboneStyle2 = NULL;
  833.                 atomStyle2.isHighlighted = GlobalMessenger()->IsHighlighted(molecule, info2->residue->id);
  834.                 bondStyle->end2.atomCap = true;
  835.                 isSpecial = true;
  836.             }
  837.             // atom2 is CD and is visible
  838.             else if (info2->code == " CD " && atomStyle2.style != eNotDisplayed && info1->code == " N  ")
  839.             {
  840.                 generalStyle1 = generalStyle2;
  841.                 backboneStyle1 = NULL;
  842.                 atomStyle1.isHighlighted = GlobalMessenger()->IsHighlighted(molecule, info1->residue->id);
  843.                 bondStyle->end1.atomCap = true;
  844.                 isSpecial = true;
  845.             }
  846.         }
  847.         // will show half-bonds in trace backbones
  848.         if (bond->order == Bond::eVirtual)
  849.             isSpecial = true;   // will set up style stuff later
  850.         // otherwise, don't show the bond at all when one atom is hidden
  851.         if (!isSpecial)
  852.             BOND_NOT_DISPLAYED;
  853.     }
  854.     // use connection style if bond is between molecules
  855.     if (atom1.mID != atom2.mID && bond->order != Bond::eRealDisulfide && bond->order != Bond::eVirtualDisulfide) {
  856.         if (globalStyle.connections.isOn == false)
  857.             BOND_NOT_DISPLAYED;
  858.         bondStyle->end1.color = bondStyle->end2.color = globalStyle.connections.userColor;
  859.         if (globalStyle.connections.style == StyleSettings::eWire)
  860.             bondStyle->end1.style = bondStyle->end2.style = eLineBond;
  861.         else if (globalStyle.connections.style == StyleSettings::eTubes) {
  862.             bondStyle->end1.style = bondStyle->end2.style = eCylinderBond;
  863.             bondStyle->end1.radius = bondStyle->end2.radius = globalStyle.tubeRadius;
  864.             bondStyle->end1.atomCap = bondStyle->end2.atomCap = true;
  865.         } else {
  866.             ERRORMSG("StyleManager::GetBondStyle() - invalid connection style");
  867.             return false;
  868.         }
  869.     }
  870.     // otherwise, need to query atom style to figure bond style parameters
  871.     else {
  872.         const StyleSettings&
  873.             settings1 = GetStyleForResidue(object, atom1.mID, atom1.rID),
  874.             settings2 = GetStyleForResidue(object, atom2.mID, atom2.rID);
  875.         StyleSettings::eDrawingStyle style1;
  876.         if (backboneStyle1)
  877.             style1 = backboneStyle1->style;
  878.         else
  879.             style1 = generalStyle1->style;
  880.         if (!SetBondStyleFromResidueStyle(style1, settings1, &(bondStyle->end1)))
  881.             return false;
  882.         StyleSettings::eDrawingStyle style2;
  883.         if (backboneStyle2)
  884.             style2 = backboneStyle2->style;
  885.         else
  886.             style2 = generalStyle2->style;
  887.         if (!SetBondStyleFromResidueStyle(style2, settings2, &(bondStyle->end2)))
  888.             return false;
  889.         // special handling of alpha virtual bonds
  890.         if (bond->order == Bond::eVirtual) {
  891.             if (backboneStyle1->type != StyleSettings::eTrace || atomStyle1.style == eNotDisplayed)
  892.                 bondStyle->end1.style = eNotDisplayed;
  893.             if (backboneStyle2->type != StyleSettings::eTrace || atomStyle2.style == eNotDisplayed)
  894.                 bondStyle->end2.style = eNotDisplayed;
  895.             if (atomStyle1.style == eNotDisplayed || atomStyle2.style == eNotDisplayed)
  896.                 bondStyle->midCap = true;
  897.             // set worm tension, tighter for smaller protein alpha-helix
  898.             if (info1->residue->IsAminoAcid())
  899.                 bondStyle->tension = -0.8;
  900.             else
  901.                 bondStyle->tension = -0.4;
  902.         }
  903.         // special case coloring and rendering for disulfides
  904.         if (bond->order == Bond::eVirtualDisulfide) {
  905.             if (backboneStyle1->type != StyleSettings::eTrace || backboneStyle2->type != StyleSettings::eTrace ||
  906.                 !settings1.virtualDisulfidesOn || !settings2.virtualDisulfidesOn)
  907.                     BOND_NOT_DISPLAYED;
  908.             // don't use worms for disulfides
  909.             if (bondStyle->end1.style == eLineWormBond) bondStyle->end1.style = eLineBond;
  910.             else if (bondStyle->end1.style == eThickWormBond) bondStyle->end1.style = eCylinderBond;
  911.             if (bondStyle->end2.style == eLineWormBond) bondStyle->end2.style = eLineBond;
  912.             else if (bondStyle->end2.style == eThickWormBond) bondStyle->end2.style = eCylinderBond;
  913.             bondStyle->end1.color = settings1.virtualDisulfideColor;
  914.             bondStyle->end2.color = settings2.virtualDisulfideColor;
  915.         }
  916.         // use atom color for all else
  917.         else {
  918.             bondStyle->end1.color = atomStyle1.color;
  919.             bondStyle->end2.color = atomStyle2.color;
  920.         }
  921.         // special case for bonds between side chain and residue - make whole bond
  922.         // same style/color as side chain side, and add endCap if atom is of lesser radius
  923.         if (info2->classification == Residue::eSideChainAtom &&
  924.             (info1->classification == Residue::eAlphaBackboneAtom ||
  925.              info1->classification == Residue::ePartialBackboneAtom ||
  926.              info1->classification == Residue::eCompleteBackboneAtom)
  927.            ) {
  928.             bondStyle->end1.style = bondStyle->end2.style;
  929.             bondStyle->end1.color = bondStyle->end2.color;
  930.             bondStyle->end1.radius = bondStyle->end2.radius;
  931.             if (atomStyle1.radius < bondStyle->end1.radius)
  932.                 bondStyle->end1.atomCap = true;
  933.         }
  934.         else if (info1->classification == Residue::eSideChainAtom &&
  935.                  (info2->classification == Residue::eAlphaBackboneAtom ||
  936.                   info2->classification == Residue::ePartialBackboneAtom ||
  937.                   info2->classification == Residue::eCompleteBackboneAtom)
  938.                 ) {
  939.             bondStyle->end2.style = bondStyle->end1.style;
  940.             bondStyle->end2.color = bondStyle->end1.color;
  941.             bondStyle->end2.radius = bondStyle->end1.radius;
  942.             if (atomStyle2.radius < bondStyle->end2.radius)
  943.                 bondStyle->end2.atomCap = true;
  944.         }
  945.         // add midCap if style or radius for two sides of bond is different;
  946.         if (bondStyle->end1.style != bondStyle->end2.style || bondStyle->end1.radius != bondStyle->end2.radius)
  947.             bondStyle->midCap = true;
  948.         // atomCaps needed at ends of thick worms when at end of chain, or if internal residues
  949.         // are hidden or of a different style, or when missing coords of prev/next bond
  950.         if (bondStyle->end1.style == eThickWormBond || bondStyle->end2.style == eThickWormBond) {
  951.             const Residue::AtomInfo *infoV;
  952.             AtomStyle atomStyleV;
  953.             const StyleSettings::BackboneStyle *backboneStyleV;
  954.             const StyleSettings::GeneralStyle *generalStyleV;
  955.             const AtomSet *atomSet;
  956.             if (!coord1->GetParentOfType(&atomSet))
  957.                 return false;
  958.             bool overlayConfs = atomSet->parentSet->showHideManager->OverlayConfEnsembles();
  959.             if (bondStyle->end1.style == eThickWormBond &&
  960.                     (!bond->previousVirtual ||
  961.                     !(infoV = object->graph->GetAtomInfo(bond->previousVirtual->atom1)) ||
  962.                     !GetAtomStyle(infoV->residue, bond->previousVirtual->atom1, NULL,
  963.                         &atomStyleV, &backboneStyleV, &generalStyleV) ||
  964.                     atomStyleV.style == eNotDisplayed ||
  965.                     backboneStyleV->style != style1 ||
  966.                     !atomSet->GetAtom(bond->previousVirtual->atom1, overlayConfs, true)))
  967.                 bondStyle->end1.atomCap = true;
  968. //            if (bondStyle->end1.atomCap)
  969. //                TRACEMSG("bondStyle->end1.atomCap true at rID " << atom1.rID);
  970.             if (bondStyle->end2.style == eThickWormBond &&
  971.                     (!bond->nextVirtual ||
  972.                     !(infoV = object->graph->GetAtomInfo(bond->nextVirtual->atom2)) ||
  973.                     !GetAtomStyle(infoV->residue, bond->nextVirtual->atom2, NULL,
  974.                         &atomStyleV, &backboneStyleV, &generalStyleV) ||
  975.                     atomStyleV.style == eNotDisplayed ||
  976.                     backboneStyleV->style != style2 ||
  977.                     !atomSet->GetAtom(bond->nextVirtual->atom2, overlayConfs, true)))
  978.                 bondStyle->end2.atomCap = true;
  979. //            if (bondStyle->end2.atomCap)
  980. //                TRACEMSG("bondStyle->end2.atomCap true at rID " << atom2.rID);
  981.         }
  982.     }
  983.     // if atom is larger than half bond length, don't show that half of the bond
  984.     bondLength /= 2;
  985.     if (atomStyle1.radius > bondLength) {
  986.         bondStyle->end1.style = eNotDisplayed;
  987.         bondStyle->midCap = true;
  988.     }
  989.     if (atomStyle2.radius > bondLength) {
  990.         bondStyle->end2.style = eNotDisplayed;
  991.         bondStyle->midCap = true;
  992.     }
  993.     // set highlighting color if necessary
  994.     if (atomStyle1.isHighlighted) bondStyle->end1.color = GlobalColors()->Get(Colors::eHighlight);
  995.     if (atomStyle2.isHighlighted) bondStyle->end2.color = GlobalColors()->Get(Colors::eHighlight);
  996.     return true;
  997. }
  998. bool StyleManager::GetObjectStyle(const StructureObject *object, const Object3D& object3D,
  999.     const StyleSettings::GeneralStyle& generalStyle, ObjectStyle *objectStyle) const
  1000. {
  1001.     // check to see if any residue covered by the object is visible
  1002.     bool anyResidueVisible = false;
  1003.     const Molecule *molecule = object->graph->molecules.find(object3D.moleculeID)->second;
  1004.     for (int r=object3D.fromResidueID; r<=object3D.toResidueID; ++r) {
  1005.         if (object->parentSet->showHideManager->IsVisible(molecule->residues.find(r)->second)) {
  1006.             anyResidueVisible = true;
  1007.             break;
  1008.         }
  1009.     }
  1010.     if (!anyResidueVisible) {
  1011.         objectStyle->style = eNotDisplayed;
  1012.         return true;
  1013.     }
  1014.     // set drawing style
  1015.     if (generalStyle.style == StyleSettings::eWithArrows) {
  1016.         objectStyle->style = eObjectWithArrow;
  1017.     } else if (generalStyle.style == StyleSettings::eWithoutArrows) {
  1018.         objectStyle->style = eObjectWithoutArrow;
  1019.     } else {
  1020.         WARNINGMSG("StyleManager::GetObjectStyle() - invalid 3d-object style");
  1021.         return false;
  1022.     }
  1023.     // set color
  1024.     switch (generalStyle.colorScheme) {
  1025.         case StyleSettings::eMolecule:
  1026.             objectStyle->color = GlobalColors()->Get(Colors::eCycle1, object3D.moleculeID - 1);
  1027.             break;
  1028.         case StyleSettings::eObject:
  1029.             objectStyle->color = GlobalColors()->Get(Colors::eCycle1, object->id - 1);
  1030.             break;
  1031.         case StyleSettings::eDomain:
  1032.             {
  1033.                 int domainID = molecule->residueDomains[object3D.fromResidueID - 1];
  1034.                 if (domainID == Molecule::NO_DOMAIN_SET)
  1035.                     objectStyle->color = GlobalColors()->Get(Colors::eNoDomain);
  1036.                 else
  1037.                     objectStyle->color = GlobalColors()->Get(Colors::eCycle1, domainID - 1);
  1038.             }
  1039.             break;
  1040.         case StyleSettings::eUserSelect:
  1041.             objectStyle->color = generalStyle.userColor;
  1042.             break;
  1043.         case StyleSettings::eSecondaryStructure:
  1044.             // set by caller
  1045.             break;
  1046.         default:
  1047.             ERRORMSG("StyleManager::GetObjectStyle() - inappropriate color scheme for 3d-object");
  1048.             return false;
  1049.     }
  1050.     return true;
  1051. }
  1052. bool StyleManager::GetHelixStyle(const StructureObject *object,
  1053.     const Helix3D& helix, HelixStyle *helixStyle) const
  1054. {
  1055.     // use style of first associated residue
  1056.     const StyleSettings&
  1057.         settings = GetStyleForResidue(object, helix.moleculeID, helix.fromResidueID);
  1058.     if (!settings.helixObjects.isOn) {
  1059.         helixStyle->style = eNotDisplayed;
  1060.         return true;
  1061.     }
  1062.     if (!GetObjectStyle(object, helix, settings.helixObjects, helixStyle))
  1063.         return false;
  1064.     // helix-specific settings
  1065.     helixStyle->radius = settings.helixRadius;
  1066.     if (settings.helixObjects.style == StyleSettings::eWithArrows) {
  1067.         helixStyle->arrowLength = 4.0;
  1068.         helixStyle->arrowBaseWidthProportion = 1.2;
  1069.         helixStyle->arrowTipWidthProportion = 0.4;
  1070.     }
  1071.     if (settings.helixObjects.colorScheme == StyleSettings::eSecondaryStructure)
  1072.         helixStyle->color = GlobalColors()->Get(Colors::eHelix);
  1073.     return true;
  1074. }
  1075. bool StyleManager::GetStrandStyle(const StructureObject *object,
  1076.     const Strand3D& strand, StrandStyle *strandStyle) const
  1077. {
  1078.     // use style of first associated residue
  1079.     const StyleSettings&
  1080.         settings = GetStyleForResidue(object, strand.moleculeID, strand.fromResidueID);
  1081.     if (!settings.strandObjects.isOn) {
  1082.         strandStyle->style = eNotDisplayed;
  1083.         return true;
  1084.     }
  1085.     if (!GetObjectStyle(object, strand, settings.strandObjects, strandStyle))
  1086.         return false;
  1087.     // strand-specific settings
  1088.     strandStyle->width = settings.strandWidth;
  1089.     strandStyle->thickness = settings.strandThickness;
  1090.     if (settings.strandObjects.style == StyleSettings::eWithArrows) {
  1091.         strandStyle->arrowLength = 2.8;
  1092.         strandStyle->arrowBaseWidthProportion = 1.6;
  1093.     }
  1094.     if (settings.strandObjects.colorScheme == StyleSettings::eSecondaryStructure)
  1095.         strandStyle->color = GlobalColors()->Get(Colors::eStrand);
  1096.     return true;
  1097. }
  1098. const StyleSettings& StyleManager::GetStyleForResidue(const StructureObject *object,
  1099.     int moleculeID, int residueID) const
  1100. {
  1101.     const Molecule *molecule = object->graph->molecules.find(moleculeID)->second;
  1102.     // find the highest priority (lowest index) annotation in the list of displayed annotations,
  1103.     // that also covers this residue
  1104.     const StyleSettings *style = &globalStyle;
  1105.     for (int d=0; d<userAnnotationsDisplayed.size(); ++d) {
  1106.         // check to see if the annotation covers this residue
  1107.         ResidueMap::const_iterator
  1108.             residues = userAnnotationsDisplayed[d]->residues.find(molecule->identifier);
  1109.         if (residues != userAnnotationsDisplayed[d]->residues.end() &&
  1110.             residues->second[residueID - 1] == true) {
  1111.             style = &(userStyles.find(userAnnotationsDisplayed[d]->styleID)->second);
  1112.             break;
  1113.         }
  1114.     }
  1115.     return *style;
  1116. }
  1117. const Vector& StyleManager::GetObjectColor(const Molecule *molecule) const
  1118. {
  1119.     static const Vector black(0,0,0);
  1120.     const StructureObject *object;
  1121.     if (!molecule || !molecule->GetParentOfType(&object)) return black;
  1122.     return GlobalColors()->Get(Colors::eCycle1, object->id - 1);
  1123. }
  1124. bool StyleManager::EditGlobalStyle(wxWindow *parent)
  1125. {
  1126.     StyleDialog dialog(parent, &globalStyle, structureSet);
  1127.     return (dialog.ShowModal() == wxOK);
  1128. }
  1129. CCn3d_style_dictionary * StyleManager::CreateASNStyleDictionary(void) const
  1130. {
  1131.     auto_ptr<CCn3d_style_dictionary> dictionary(new CCn3d_style_dictionary());
  1132.     if (!globalStyle.SaveSettingsToASN(&(dictionary->SetGlobal_style()))) return NULL;
  1133.     if (userStyles.size() > 0) {
  1134.         // create an ordered list of style id's
  1135.         typedef list < int > IntList;
  1136.         IntList keys;
  1137.         StyleMap::const_iterator s, se = userStyles.end();
  1138.         for (s=userStyles.begin(); s!=se; ++s) keys.push_back(s->first);
  1139.         keys.sort();
  1140.         // create a new style table entry for each user style
  1141.         IntList::const_iterator i, ie = keys.end();
  1142.         for (i=keys.begin(); i!=ie; ++i) {
  1143.             CRef < CCn3d_style_table_item > entry(new CCn3d_style_table_item());
  1144.             entry->SetId().Set(*i);
  1145.             if (!userStyles.find(*i)->second.SaveSettingsToASN(&(entry->SetStyle()))) return NULL;
  1146.             dictionary->SetStyle_table().push_back(entry);
  1147.         }
  1148.     }
  1149.     return dictionary.release();
  1150. }
  1151. bool StyleManager::LoadFromASNStyleDictionary(const CCn3d_style_dictionary& styleDictionary)
  1152. {
  1153.     if (!globalStyle.LoadSettingsFromASN(styleDictionary.GetGlobal_style())) return false;
  1154.     userStyles.clear();
  1155.     if (styleDictionary.IsSetStyle_table()) {
  1156.         CCn3d_style_dictionary::TStyle_table::const_iterator t, te = styleDictionary.GetStyle_table().end();
  1157.         for (t=styleDictionary.GetStyle_table().begin(); t!=te; ++t) {
  1158.             int id = (*t)->GetId().Get();
  1159.             if (userStyles.find(id) != userStyles.end()) {
  1160.                 ERRORMSG("repeated style table id in style dictionary");
  1161.                 return false;
  1162.             } else
  1163.                 if (!userStyles[id].LoadSettingsFromASN((*t)->GetStyle())) return false;
  1164.         }
  1165.     }
  1166.     return true;
  1167. }
  1168. bool StyleManager::EditUserAnnotations(wxWindow *parent)
  1169. {
  1170.     AnnotateDialog dialog(parent, this, structureSet);
  1171.     dialog.ShowModal();
  1172.     return false;
  1173. }
  1174. void StyleManager::GetUserAnnotations(AnnotationPtrList *annotationList)
  1175. {
  1176.     annotationList->resize(userAnnotations.size());
  1177.     AnnotationList::iterator a = userAnnotations.begin();
  1178.     for (int i=0; i<userAnnotations.size(); ++i)
  1179.         (*annotationList)[i] = &(*(a++));
  1180. }
  1181. bool StyleManager::AddUserStyle(int *id, StyleSettings **newStyle)
  1182. {
  1183.     // create a style with the lowest integer id (above zero) available
  1184.     static const int max = 10000;
  1185.     for (int i=1; i<max; ++i) {
  1186.         if (userStyles.find(i) == userStyles.end()) {
  1187.             *newStyle = &(userStyles[i]);
  1188.             *id = i;
  1189.             structureSet->SetDataChanged(StructureSet::eStyleData);
  1190.             return true;
  1191.         }
  1192.     }
  1193.     return false;
  1194. }
  1195. bool StyleManager::RemoveUserStyle(int id)
  1196. {
  1197.     StyleMap::iterator u = userStyles.find(id);
  1198.     if (u == userStyles.end()) return false;
  1199.     userStyles.erase(u);
  1200.     structureSet->SetDataChanged(StructureSet::eStyleData);
  1201.     return true;
  1202. }
  1203. StyleManager::UserAnnotation * StyleManager::AddUserAnnotation(void)
  1204. {
  1205.     userAnnotations.resize(userAnnotations.size() + 1);
  1206.     structureSet->SetDataChanged(StructureSet::eStyleData);
  1207.     return &(userAnnotations.back());
  1208. }
  1209. bool StyleManager::RemoveUserAnnotation(UserAnnotation *annotation)
  1210. {
  1211.     // remove annotation from displayed list
  1212.     AnnotationPtrList::iterator d, de = userAnnotationsDisplayed.end();
  1213.     for (d=userAnnotationsDisplayed.begin(); d!=de; ++d) {
  1214.         if (annotation == *d) {
  1215.             userAnnotationsDisplayed.erase(d);
  1216.             GlobalMessenger()->PostRedrawAllStructures();
  1217.             GlobalMessenger()->PostRedrawAllSequenceViewers();
  1218.             break;
  1219.         }
  1220.     }
  1221.     // remove annotation from available list
  1222.     AnnotationList::iterator u, ue = userAnnotations.end();
  1223.     int removedStyleID = -1;
  1224.     for (u=userAnnotations.begin(); u!=ue; ++u) {
  1225.         if (annotation == &(*u)) {
  1226.             removedStyleID = u->styleID;
  1227.             userAnnotations.erase(u);
  1228.             break;
  1229.         }
  1230.     }
  1231.     if (u == ue) return false;
  1232.     // also remove the style if it's not used by any other annotation
  1233.     for (u=userAnnotations.begin(); u!=ue; ++u)
  1234.         if (u->styleID == removedStyleID) break;
  1235.     if (u == ue) RemoveUserStyle(removedStyleID);
  1236.     structureSet->SetDataChanged(StructureSet::eStyleData);
  1237.     return true;
  1238. }
  1239. bool StyleManager::DisplayAnnotation(UserAnnotation *annotation, bool display)
  1240. {
  1241.     // first check to make sure this annotation is known
  1242.     AnnotationList::const_iterator a, ae = userAnnotations.end();
  1243.     for (a=userAnnotations.begin(); a!=ae; ++a)
  1244.         if (annotation == &(*a)) break;
  1245.     if (a == ae) return false;
  1246.     // then look for it in the list of displayed annotations
  1247.     AnnotationPtrList::iterator d, de = userAnnotationsDisplayed.end();
  1248.     for (d=userAnnotationsDisplayed.begin(); d!=de; ++d)
  1249.         if (annotation == *d) break;
  1250.     // finally, add or remove it from the displayed annotations
  1251.     bool changed = false;
  1252.     if (display && d == de) {
  1253.         userAnnotationsDisplayed.insert(userAnnotationsDisplayed.begin(), annotation);
  1254.         changed = true;
  1255.     } else if (!display && d != de) {
  1256.         userAnnotationsDisplayed.erase(d);
  1257.         changed = true;
  1258.     }
  1259.     if (changed) {  // need to redraw if displayed annotations list has changed
  1260.         GlobalMessenger()->PostRedrawAllStructures();
  1261.         GlobalMessenger()->PostRedrawAllSequenceViewers();
  1262.         structureSet->SetDataChanged(StructureSet::eStyleData);
  1263.     }
  1264.     return true;
  1265. }
  1266. bool StyleManager::ReprioritizeDisplayOrder(UserAnnotation *annotation, bool moveUp)
  1267. {
  1268.     // look for the annotation in the list of displayed annotations
  1269. int d;
  1270.     for (d=0; d<userAnnotationsDisplayed.size(); ++d)
  1271.         if (annotation == userAnnotationsDisplayed[d]) break;
  1272.     if (d == userAnnotationsDisplayed.size()) return false;
  1273.     bool changed = false;
  1274.     if (moveUp && d > 0) {
  1275.         userAnnotationsDisplayed[d] = userAnnotationsDisplayed[d - 1];
  1276.         userAnnotationsDisplayed[d - 1] = annotation;
  1277.         changed = true;
  1278.     } else if (!moveUp && d < userAnnotationsDisplayed.size() - 1) {
  1279.         userAnnotationsDisplayed[d] = userAnnotationsDisplayed[d + 1];
  1280.         userAnnotationsDisplayed[d + 1] = annotation;
  1281.         changed = true;
  1282.     }
  1283.     if (changed) {  // need to redraw if displayed annotations list has changed
  1284.         GlobalMessenger()->PostRedrawAllStructures();
  1285.         GlobalMessenger()->PostRedrawAllSequenceViewers();
  1286.         structureSet->SetDataChanged(StructureSet::eStyleData);
  1287.     }
  1288.     return true;
  1289. }
  1290. static bool CreateObjectLocation(
  1291.     CCn3d_user_annotation::TResidues *residuesASN,
  1292.     const StyleManager::ResidueMap& residueMap)
  1293. {
  1294.     residuesASN->clear();
  1295.     StyleManager::ResidueMap::const_iterator r, re = residueMap.end();
  1296.     for (r=residueMap.begin(); r!=re; ++r) {
  1297.         // find an existing object location that matches this MMDB ID
  1298.         CCn3d_user_annotation::TResidues::iterator l, le = residuesASN->end();
  1299.         for (l=residuesASN->begin(); l!=le; ++l)
  1300.             if ((*l)->GetStructure_id().GetMmdb_id().Get() == r->first->mmdbID) break;
  1301.         // if necessary, create new object location, with Biostruc-id from MMDB ID
  1302.         if (l == le) {
  1303.             CRef < CCn3d_object_location > loc(new CCn3d_object_location());
  1304.             if (r->first->mmdbID != MoleculeIdentifier::VALUE_NOT_SET) {
  1305.                 CMmdb_id *mmdbID = new CMmdb_id();
  1306.                 mmdbID->Set(r->first->mmdbID);
  1307.                 loc->SetStructure_id().SetMmdb_id(*mmdbID);
  1308.             } else {
  1309.                 ERRORMSG("CreateObjectLocation() - MoleculeIdentifier must (currently) have MMDB ID");
  1310.                 return false;
  1311.             }
  1312.             residuesASN->push_back(loc);
  1313.             l = residuesASN->end();
  1314.             --l;    // set iterator to the new object location
  1315.         }
  1316.         // set molecule location
  1317.         CRef < CCn3d_molecule_location > molecule(new CCn3d_molecule_location());
  1318.         molecule->SetMolecule_id().Set(r->first->moleculeID);
  1319.         (*l)->SetResidues().push_back(molecule);
  1320.         // check if covers whole molecule; if so, leave 'residues' field of Cn3d_molecule_location blank
  1321.         int i;
  1322.         for (i=0; i<r->second.size(); ++i)
  1323.             if (!r->second[i]) break;
  1324.         // else break list down into individual contiguous residue ranges
  1325.         if (i != r->second.size()) {
  1326.             int first = 0, last = 0;
  1327.             while (first < r->second.size()) {
  1328.                 // find first included residue
  1329.                 while (first < r->second.size() && !r->second[first]) ++first;
  1330.                 if (first >= r->second.size()) break;
  1331.                 // find last in contiguous stretch of included residues
  1332.                 last = first;
  1333.                 while (last + 1 < r->second.size() && r->second[last + 1]) ++last;
  1334.                 CRef < CCn3d_residue_range > range(new CCn3d_residue_range());
  1335.                 range->SetFrom().Set(first + 1);    // assume moleculeID = index + 1
  1336.                 range->SetTo().Set(last + 1);
  1337.                 molecule->SetResidues().push_back(range);
  1338.                 first = last + 2;
  1339.             }
  1340.             if (molecule->GetResidues().size() == 0) {
  1341.                 ERRORMSG("CreateObjectLocation() - no residue ranges found");
  1342.                 return false;
  1343.             }
  1344.         }
  1345.     }
  1346.     return true;
  1347. }
  1348. bool StyleManager::SaveToASNUserAnnotations(ncbi::objects::CCn3d_user_annotations *annotations) const
  1349. {
  1350.     if (!annotations) return false;
  1351.     annotations->ResetAnnotations();
  1352.     if (userAnnotations.size() == 0) return true;
  1353.     AnnotationList::const_iterator a, ae = userAnnotations.end();
  1354.     AnnotationPtrList::const_iterator d, de = userAnnotationsDisplayed.end();
  1355.     for (a=userAnnotations.begin(); a!=ae; ++a) {
  1356.         // fill out individual annotations
  1357.         CRef < CCn3d_user_annotation > annotation(new CCn3d_user_annotation());
  1358.         annotation->SetName(a->name);
  1359.         annotation->SetDescription(a->description);
  1360.         annotation->SetStyle_id().Set(a->styleID);
  1361.         // is this annotation on? check displayed annotations list
  1362.         for (d=userAnnotationsDisplayed.begin(); d!=de; ++d)
  1363.             if (*d == &(*a)) break;
  1364.         annotation->SetIs_on(d != de);
  1365.         // fill out residues list
  1366.         if (!CreateObjectLocation(&(annotation->SetResidues()), a->residues)) {
  1367.             ERRORMSG("StyleManager::CreateASNUserAnnotations() - error creating object location");
  1368.             return false;
  1369.         }
  1370.         annotations->SetAnnotations().push_back(annotation);
  1371.     }
  1372.     return true;
  1373. }
  1374. static bool ExtractObjectLocation(
  1375.     StyleManager::ResidueMap *residueMap,
  1376.     const CCn3d_user_annotation::TResidues& residuesASN)
  1377. {
  1378.     CCn3d_user_annotation::TResidues::const_iterator o, oe = residuesASN.end();
  1379.     for (o=residuesASN.begin(); o!=oe; ++o) {
  1380.         int mmdbID;
  1381.         if ((*o)->GetStructure_id().IsMmdb_id()) {
  1382.             mmdbID = (*o)->GetStructure_id().GetMmdb_id().Get();
  1383.         } else {
  1384.             ERRORMSG("ExtractObjectLocation() - can't handle non-MMDB identifiers (yet)");
  1385.             return false;
  1386.         }
  1387.         // extract molecules
  1388.         CCn3d_object_location::TResidues::const_iterator m, me = (*o)->GetResidues().end();
  1389.         for (m=(*o)->GetResidues().begin(); m!=me; ++m) {
  1390.             int moleculeID = (*m)->GetMolecule_id().Get();
  1391.             // get identifier for this molecule
  1392.             const MoleculeIdentifier *identifier = MoleculeIdentifier::FindIdentifier(mmdbID, moleculeID);
  1393.             if (!identifier) {
  1394.                 WARNINGMSG("ExtractObjectLocation() - can't find identifier for molecule location");
  1395.                 WARNINGMSG("structure MMDB ID " << mmdbID << " not loaded?");
  1396.                 continue;
  1397.             }
  1398.             // set residue ranges
  1399.             int i;
  1400.             vector < bool >& residueFlags = (*residueMap)[identifier];
  1401.             if (residueFlags.size() == 0)
  1402.                 residueFlags.resize(identifier->nResidues, false);
  1403.             if ((*m)->IsSetResidues()) {
  1404.                 // parse individual ranges
  1405.                 CCn3d_molecule_location::TResidues::const_iterator r, re = (*m)->GetResidues().end();
  1406.                 for (r=(*m)->GetResidues().begin(); r!=re; ++r) {
  1407.                     for (i=(*r)->GetFrom().Get(); i<=(*r)->GetTo().Get(); ++i) {
  1408.                         if (i > 0 && i <= residueFlags.size()) {
  1409.                             residueFlags[i - 1] = true;     // assume index = residue id - 1
  1410.                         } else {
  1411.                             ERRORMSG("ExtractObjectLocation() - residue from/to out of range");
  1412.                             return false;
  1413.                         }
  1414.                     }
  1415.                 }
  1416.             } else {
  1417.                 // assume all residues are included if none specified
  1418.                 for (i=0; i<residueFlags.size(); ++i) residueFlags[i] = true;
  1419.             }
  1420.         }
  1421.     }
  1422. return true;
  1423. }
  1424. bool StyleManager::LoadFromASNUserAnnotations(const ncbi::objects::CCn3d_user_annotations& annotations)
  1425. {
  1426.     if (!annotations.IsSetAnnotations()) return true;
  1427.     CCn3d_user_annotations::TAnnotations::const_iterator a, ae = annotations.GetAnnotations().end();
  1428.     for (a=annotations.GetAnnotations().begin(); a!=ae; ++a) {
  1429.         UserAnnotation *userAnnot = AddUserAnnotation();
  1430.         // fill out annotation parameters
  1431.         userAnnot->name = (*a)->GetName();
  1432.         if ((*a)->IsSetDescription())
  1433.             userAnnot->description = (*a)->GetDescription();
  1434.         userAnnot->styleID = (*a)->GetStyle_id().Get();
  1435.         DisplayAnnotation(userAnnot, (*a)->GetIs_on());
  1436.         // extract object locations
  1437.         if (!ExtractObjectLocation(&(userAnnot->residues), (*a)->GetResidues()))
  1438.             return false;
  1439.     }
  1440.     return true;
  1441. }
  1442. void StyleManager::SetGlobalColorScheme(StyleSettings::ePredefinedColorScheme scheme)
  1443. {
  1444.     globalStyle.SetColorScheme(scheme);
  1445. //    structureSet->SetDataChanged(StructureSet::eStyleData);
  1446. }
  1447. void StyleManager::SetGlobalRenderingStyle(StyleSettings::ePredefinedRenderingStyle style)
  1448. {
  1449.     globalStyle.SetRenderingStyle(style);
  1450. //    structureSet->SetDataChanged(StructureSet::eStyleData);
  1451. }
  1452. bool StyleManager::SetGlobalStyle(const ncbi::objects::CCn3d_style_settings& styleASN)
  1453. {
  1454.     bool okay = globalStyle.LoadSettingsFromASN(styleASN);
  1455.     if (okay) {
  1456.         CheckGlobalStyleSettings();
  1457. //        structureSet->SetDataChanged(StructureSet::eStyleData);
  1458.         GlobalMessenger()->PostRedrawAllStructures();
  1459.         GlobalMessenger()->PostRedrawAllSequenceViewers();
  1460.     }
  1461.     return okay;
  1462. }
  1463. END_SCOPE(Cn3D)
  1464. /*
  1465. * ---------------------------------------------------------------------------
  1466. * $Log: style_manager.cpp,v $
  1467. * Revision 1000.2  2004/06/01 18:29:44  gouriano
  1468. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.84
  1469. *
  1470. * Revision 1.84  2004/05/28 19:10:28  thiessen
  1471. * fix typos
  1472. *
  1473. * Revision 1.83  2004/05/27 13:40:50  thiessen
  1474. * more cleanup ; use residue rather than global style for disulfides
  1475. *
  1476. * Revision 1.82  2004/05/26 22:18:42  thiessen
  1477. * fix display of single residues with trace backbone
  1478. *
  1479. * Revision 1.81  2004/05/21 21:41:40  gorelenk
  1480. * Added PCH ncbi_pch.hpp
  1481. *
  1482. * Revision 1.80  2004/03/15 18:11:01  thiessen
  1483. * prefer prefix vs. postfix ++/-- operators
  1484. *
  1485. * Revision 1.79  2004/02/19 17:05:19  thiessen
  1486. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  1487. *
  1488. * Revision 1.78  2004/01/19 17:27:14  thiessen
  1489. * add Proline CD-N bond for sidechain display
  1490. *
  1491. * Revision 1.77  2004/01/19 16:17:37  thiessen
  1492. * fix worm display problem when coords of prev/next alpha are missing
  1493. *
  1494. * Revision 1.76  2003/07/22 18:54:42  thiessen
  1495. * fix object access bug
  1496. *
  1497. * Revision 1.75  2003/06/21 08:18:58  thiessen
  1498. * show all atoms with coordinates, even if not in all coord sets
  1499. *
  1500. * Revision 1.74  2003/03/13 14:26:18  thiessen
  1501. * add file_messaging module; split cn3d_main_wxwin into cn3d_app, cn3d_glcanvas, structure_window, cn3d_tools
  1502. *
  1503. * Revision 1.73  2003/02/06 16:39:53  thiessen
  1504. * add block row fit coloring
  1505. *
  1506. * Revision 1.72  2003/02/03 19:20:08  thiessen
  1507. * format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros
  1508. *
  1509. * Revision 1.71  2003/01/30 14:00:23  thiessen
  1510. * add Block Z Fit coloring
  1511. *
  1512. * Revision 1.70  2003/01/28 21:07:56  thiessen
  1513. * add block fit coloring algorithm; tweak row dragging; fix style bug
  1514. *
  1515. * Revision 1.69  2002/11/18 20:49:11  thiessen
  1516. * move unaligned/no-coord colors into Colors class
  1517. *
  1518. * Revision 1.68  2002/11/10 01:26:16  thiessen
  1519. * tweak loading of style annotation residue ranges
  1520. *
  1521. * Revision 1.67  2002/08/15 22:13:18  thiessen
  1522. * update for wx2.3.2+ only; add structure pick dialog; fix MultitextDialog bug
  1523. *
  1524. * Revision 1.66  2002/04/27 16:32:15  thiessen
  1525. * fix small leaks/bugs found by BoundsChecker
  1526. *
  1527. * Revision 1.65  2002/04/12 01:54:43  thiessen
  1528. * tweaks to style stuff
  1529. *
  1530. * Revision 1.64  2002/04/11 17:50:28  thiessen
  1531. * fix domain coloring bug
  1532. *
  1533. * Revision 1.63  2002/04/11 16:39:56  thiessen
  1534. * fix style manager bug
  1535. *
  1536. * Revision 1.62  2002/02/22 20:46:57  thiessen
  1537. * more rigorous fix for same
  1538. *
  1539. * Revision 1.61  2002/02/22 20:17:24  thiessen
  1540. * fix feature range problems
  1541. *
  1542. * Revision 1.60  2002/01/19 02:34:50  thiessen
  1543. * fixes for changes in asn serialization API
  1544. *
  1545. * Revision 1.59  2001/12/12 14:04:15  thiessen
  1546. * add missing object headers after object loader change
  1547. *
  1548. * Revision 1.58  2001/12/06 23:13:46  thiessen
  1549. * finish import/align new sequences into single-structure data; many small tweaks
  1550. *
  1551. * Revision 1.57  2001/11/27 16:26:10  thiessen
  1552. * major update to data management system
  1553. *
  1554. * Revision 1.56  2001/10/24 17:13:46  thiessen
  1555. * skip style annotation if structure not loaded
  1556. *
  1557. * Revision 1.55  2001/10/17 17:46:22  thiessen
  1558. * save camera setup and rotation center in files
  1559. *
  1560. * Revision 1.54  2001/09/18 03:10:46  thiessen
  1561. * add preliminary sequence import pipeline
  1562. *
  1563. * Revision 1.53  2001/09/04 14:40:19  thiessen
  1564. * add rainbow and charge coloring
  1565. *
  1566. * Revision 1.52  2001/08/24 00:41:36  thiessen
  1567. * tweak conservation colors and opengl font handling
  1568. *
  1569. * Revision 1.51  2001/08/21 01:10:46  thiessen
  1570. * add labeling
  1571. *
  1572. * Revision 1.50  2001/08/13 22:30:59  thiessen
  1573. * add structure window mouse drag/zoom; add highlight option to render settings
  1574. *
  1575. * Revision 1.49  2001/08/10 15:01:58  thiessen
  1576. * fill out shortcuts; add update show/hide menu
  1577. *
  1578. * Revision 1.48  2001/08/09 19:07:14  thiessen
  1579. * add temperature and hydrophobicity coloring
  1580. *
  1581. * Revision 1.47  2001/08/03 13:41:33  thiessen
  1582. * add registry and style favorites
  1583. *
  1584. * Revision 1.46  2001/07/12 17:35:15  thiessen
  1585. * change domain mapping ; add preliminary cdd annotation GUI
  1586. *
  1587. * Revision 1.45  2001/07/04 19:39:17  thiessen
  1588. * finish user annotation system
  1589. *
  1590. * Revision 1.44  2001/06/29 18:54:46  thiessen
  1591. * fix mysterious CRef error in MSVC MT compile mode
  1592. *
  1593. * Revision 1.43  2001/06/29 18:13:58  thiessen
  1594. * initial (incomplete) user annotation system
  1595. *
  1596. * Revision 1.42  2001/06/21 02:02:34  thiessen
  1597. * major update to molecule identification and highlighting ; add toggle highlight (via alt)
  1598. *
  1599. * Revision 1.41  2001/06/15 14:06:40  thiessen
  1600. * save/load asn styles now complete
  1601. *
  1602. * Revision 1.40  2001/06/15 13:00:05  thiessen
  1603. * fix enumerated type casts fo unix compilers
  1604. *
  1605. * Revision 1.39  2001/06/15 02:23:00  thiessen
  1606. * fill code for settings<->asn
  1607. *
  1608. * Revision 1.38  2001/06/14 17:45:10  thiessen
  1609. * progress in styles<->asn ; add structure limits
  1610. *
  1611. * Revision 1.37  2001/06/14 00:34:02  thiessen
  1612. * asn additions
  1613. *
  1614. * Revision 1.36  2001/06/08 14:47:06  thiessen
  1615. * fully functional (modal) render settings panel
  1616. *
  1617. * Revision 1.35  2001/06/07 19:05:38  thiessen
  1618. * functional (although incomplete) render settings panel ; highlight title - not sequence - upon mouse click
  1619. *
  1620. * Revision 1.34  2001/06/01 13:01:00  thiessen
  1621. * fix wx-string problem again...
  1622. *
  1623. * Revision 1.33  2001/05/31 18:47:10  thiessen
  1624. * add preliminary style dialog; remove LIST_TYPE; add thread single and delete all; misc tweaks
  1625. *
  1626. * Revision 1.32  2001/05/15 23:48:38  thiessen
  1627. * minor adjustments to compile under Solaris/wxGTK
  1628. *
  1629. * Revision 1.31  2001/03/29 15:49:21  thiessen
  1630. * use disulfide color only for virtual disulfides
  1631. *
  1632. * Revision 1.30  2001/03/29 15:32:42  thiessen
  1633. * change disulfide, connection colors to not-yellow
  1634. *
  1635. * Revision 1.29  2001/03/23 23:31:56  thiessen
  1636. * keep atom info around even if coords not all present; mainly for disulfide parsing in virtual models
  1637. *
  1638. * Revision 1.28  2001/03/23 15:14:07  thiessen
  1639. * load sidechains in CDD's
  1640. *
  1641. * Revision 1.27  2001/03/23 04:18:53  thiessen
  1642. * parse and display disulfides
  1643. *
  1644. * Revision 1.26  2001/03/22 00:33:17  thiessen
  1645. * initial threading working (PSSM only); free color storage in undo stack
  1646. *
  1647. * Revision 1.25  2001/03/09 15:49:05  thiessen
  1648. * major changes to add initial update viewer
  1649. *
  1650. * Revision 1.24  2001/02/13 20:33:50  thiessen
  1651. * add information content coloring
  1652. *
  1653. * Revision 1.23  2001/02/08 23:01:51  thiessen
  1654. * hook up C-toolkit stuff for threading; working PSSM calculation
  1655. *
  1656. * Revision 1.22  2001/01/30 20:51:20  thiessen
  1657. * minor fixes
  1658. *
  1659. * Revision 1.21  2000/12/15 15:51:48  thiessen
  1660. * show/hide system installed
  1661. *
  1662. * Revision 1.20  2000/12/01 19:35:57  thiessen
  1663. * better domain assignment; basic show/hide mechanism
  1664. *
  1665. * Revision 1.19  2000/11/30 15:49:40  thiessen
  1666. * add show/hide rows; unpack sec. struc. and domain features
  1667. *
  1668. * Revision 1.18  2000/10/16 14:25:48  thiessen
  1669. * working alignment fit coloring
  1670. *
  1671. * Revision 1.17  2000/10/05 18:34:43  thiessen
  1672. * first working editing operation
  1673. *
  1674. * Revision 1.16  2000/09/20 22:22:30  thiessen
  1675. * working conservation coloring; split and center unaligned justification
  1676. *
  1677. * Revision 1.15  2000/09/15 19:24:22  thiessen
  1678. * allow repeated structures w/o different local id
  1679. *
  1680. * Revision 1.14  2000/09/11 22:57:34  thiessen
  1681. * working highlighting
  1682. *
  1683. * Revision 1.13  2000/09/11 14:06:30  thiessen
  1684. * working alignment coloring
  1685. *
  1686. * Revision 1.12  2000/09/08 20:16:55  thiessen
  1687. * working dynamic alignment views
  1688. *
  1689. * Revision 1.11  2000/08/24 23:40:19  thiessen
  1690. * add 'atomic ion' labels
  1691. *
  1692. * Revision 1.10  2000/08/24 18:43:52  thiessen
  1693. * tweaks for transparent sphere display
  1694. *
  1695. * Revision 1.9  2000/08/21 19:31:48  thiessen
  1696. * add style consistency checking
  1697. *
  1698. * Revision 1.8  2000/08/21 17:22:38  thiessen
  1699. * add primitive highlighting for testing
  1700. *
  1701. * Revision 1.7  2000/08/18 18:57:40  thiessen
  1702. * added transparent spheres
  1703. *
  1704. * Revision 1.6  2000/08/17 18:33:12  thiessen
  1705. * minor fixes to StyleManager
  1706. *
  1707. * Revision 1.5  2000/08/17 14:24:07  thiessen
  1708. * added working StyleManager
  1709. *
  1710. * Revision 1.4  2000/08/13 02:43:02  thiessen
  1711. * added helix and strand objects
  1712. *
  1713. * Revision 1.3  2000/08/11 12:58:31  thiessen
  1714. * added worm; get 3d-object coords from asn1
  1715. *
  1716. * Revision 1.2  2000/08/04 22:49:04  thiessen
  1717. * add backbone atom classification and selection feedback mechanism
  1718. *
  1719. * Revision 1.1  2000/08/03 15:13:59  thiessen
  1720. * add skeleton of style and show/hide managers
  1721. *
  1722. */