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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: align_row.cpp,v $
  4.  * PRODUCTION Revision 1000.5  2004/06/01 21:07:00  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.41
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: align_row.cpp,v 1000.5 2004/06/01 21:07:00 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:  Andrey Yazhuk
  35.  *
  36.  * File Description:
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbistd.hpp>
  41. #include <corelib/ncbitime.hpp>
  42. #include <math.h>
  43. #include <gui/types.hpp>
  44. #include <gui/opengl/glhelpers.hpp>
  45. #include <gui/opengl/glbitmapfont.hpp>
  46. #include <objmgr/graph_ci.hpp>
  47. #include <objects/general/Dbtag.hpp>
  48. #include <objects/general/Object_id.hpp>
  49. #include <gui/widgets/aln_multiple/align_row.hpp>
  50. #include <gui/widgets/aln_multiple/aln_scoring.hpp>
  51. #include <gui/widgets/aln_multiple/trace_graph.hpp>
  52. #include <objmgr/util/sequence.hpp>
  53. #include <FL/Fl.H>
  54. BEGIN_NCBI_SCOPE
  55. USING_SCOPE(ncbi::objects);
  56. ////////////////////////////////////////////////////////////////////////////////
  57. ///
  58. const CGlColor&   CAlnVecRowDisplayStyle::GetAlignTextColor() const
  59. {
  60.     return m_AlignTextColor;
  61. }
  62. const CGlColor&   CAlnVecRowDisplayStyle::GetAlignColor() const
  63. {
  64.     return m_AlignColor;
  65. }
  66. ////////////////////////////////////////////////////////////////////////////////
  67. /// CAlnVecRow
  68. CAlnVecRow::CAlnVecRow(const CAlnVecRowHandle& handle)
  69. :   m_Handle(handle),
  70.     m_pHost(NULL),
  71.     m_BaseHeight(0),
  72.     m_bExpanded(false),
  73.     m_pStyle(NULL),
  74.     m_pCache(NULL),
  75.     m_pGraph(NULL),
  76.     m_PixLeft(-1), m_PixRight(-1), m_ModelLeft(-1), m_ModelRight(-1)
  77. {
  78.     const CSeq_id& id = sequence::GetId(m_Handle.GetBioseqHandle(),
  79.                                         sequence::eGetId_Best);
  80.     id.GetLabel(&m_Text);
  81.     /// instantiate but do not create
  82.     m_pGraph = new CTraceGraph(handle.GetBioseqHandle(), handle.IsNegativeStrand());
  83.     m_bExpanded = false;
  84. }
  85. CAlnVecRow::~CAlnVecRow()
  86. {
  87.     delete m_pGraph;
  88.     m_DList.Delete();
  89.     m_pStyle = NULL; //do not delete
  90. }
  91. void    CAlnVecRow::x_CreateGraph()
  92. {
  93.     m_pGraph->Create();
  94. }
  95. void    CAlnVecRow::x_DestroyGraph()
  96. {
  97.     m_pGraph->Destroy();
  98. }
  99. void    CAlnVecRow::SetScoreCache(CScoreCache* cache)
  100. {
  101.     m_pCache = cache;
  102. }
  103. void    CAlnVecRow::GraphicsCacheCmd(EGraphCacheCmd cmd)
  104. {
  105.     switch(cmd) {
  106.     case eInvalidate: m_DList.Invalidate(); break;
  107.     case eDelete: m_DList.Delete(); break;
  108.     }
  109. }
  110. void    CAlnVecRow::GetHTMLActiveAreas(EColumnType col_type, CGlPane& pane, TAreaVector& areas)
  111. {
  112.     switch(col_type)    {
  113.     case eIcons:    {
  114.         string s_row = NStr::IntToString(m_Handle.GetRowNum());
  115.         CHTMLActiveArea area(CHTMLActiveArea::eCheckBox,
  116.                              x_GetButtonRect(pane, eExpand),
  117.                             s_row, "Click to expand/collapse", "toggle_expand");
  118.         areas.push_back(area);
  119.     }; break;
  120.     case eAlignment:    {
  121.         // create area for alignment
  122.         TSignedSeqPos start = m_Handle.GetSeqAlnStart();
  123.         TSignedSeqPos stop = m_Handle.GetSeqAlnStop();
  124.         const TModelRect& rc_vis = pane.GetVisibleRect();
  125.         start = max(start, (TSignedSeqPos) floor(rc_vis.Left()) );
  126.         stop = min(stop, (TSignedSeqPos) ceil(rc_vis.Right()) );
  127.         
  128.         pane.OpenOrtho();
  129.         pane.Close();
  130.         TVPUnit vp_start = pane.ProjectX(start);
  131.         TVPUnit vp_stop = pane.ProjectX(stop);
  132.         TVPRect rc = pane.GetViewport();
  133.         rc.SetHorz(vp_start, vp_stop);
  134.         
  135.         string s_row = NStr::IntToString(m_Handle.GetRowNum());
  136.         CHTMLActiveArea area(CHTMLActiveArea::eLink, rc,
  137.                              s_row, m_Text, "");
  138.         areas.push_back(area);
  139.     }; break;
  140.     default: break;
  141.     };
  142. }
  143. /// height of "white-space" between row borders and alignment band
  144. static const int kAlignSpace = 2;
  145. /// height of sub-bands where the colored according to the exreme score values (min or max)
  146. static const int kExtremeArea = 3;
  147. static const int kGapExtremeArea = 1;
  148. /// vertical offset from the border of the alignment band to the border of gap band
  149. static const int kGapOffset = 4;
  150. static const int kTextVertSpace = 1;
  151. static const int kSeqVertSpace = kAlignSpace + 2;
  152. void    CAlnVecRow::SetDisplayStyle(const CRowDisplayStyle* style)
  153. {
  154.     m_pStyle = dynamic_cast<const CAlnVecRowDisplayStyle*>(style);
  155.     float h1 = kTextVertSpace * 2;
  156.     float h2 = kSeqVertSpace * 2;
  157.     if(m_pStyle)
  158.     {
  159.         h1 += m_pStyle->GetTextFont().TextHeight();
  160.         h2 += m_pStyle->GetSeqFont().TextHeight();
  161.     }
  162.     m_Height = m_BaseHeight = (int) max(h1, h2);
  163.     if(m_bExpanded) {
  164.         if(m_pGraph)   {
  165.             m_Height += m_pGraph->GetPreferredHeight();
  166.         }
  167.     }
  168. }
  169. const CRowDisplayStyle*    CAlnVecRow::GetDisplayStyle()
  170. {
  171.     return m_pStyle;
  172. }
  173. void    CAlnVecRow::SetHost(IAlignRowHost* pHost)
  174. {
  175.     m_pHost = pHost;
  176. }
  177. int CAlnVecRow::GetRowNum()  const
  178. {
  179.     return m_Handle.GetRowNum();
  180. }
  181. int CAlnVecRow::GetHeightPixels()    const
  182. {
  183.     return m_Height;
  184. }
  185. void    CAlnVecRow::RenderColumn(EColumnType  col_type, CGlPane& pane, int State)
  186. {
  187.     CGlAttrGuard AttrGuard(GL_POLYGON_MODE);
  188.     if(m_pStyle)    {
  189.         switch(col_type) {
  190.         case eDescr:    x_RenderDescr(pane, State); break;
  191.         case eIcons: x_RenderIcons(pane); break;
  192.         case eStart: x_RenderStartPos(pane); break;
  193.         case eAlignment:    x_RenderAlign(pane); break;
  194.         case eEnd: x_RenderEndPos(pane); break;
  195.         case eSeqEnd: x_RenderSeqEnd(pane); break;
  196.         default: break; // unknown column
  197.         }
  198.     }
  199. }
  200. int     CAlnVecRow::handle(CGUIEvent& event, EColumnType  col_type, CGlPane& pane)
  201. {
  202.     switch(event.GetFLTKEvent())    {
  203.     case FL_PUSH: {
  204.         if(Fl::event_button() == FL_LEFT_MOUSE) {
  205.             TVPPoint pt = x_GetHost()->ARH_GetVPMousePos();
  206.             TVPRect rc_btn = x_GetButtonRect(pane, eExpand);
  207.             if(rc_btn.PtInRect(pt)) {
  208.                 x_OnClickExpandBtn();
  209.                 return 1;
  210.             }
  211.         }
  212.     }; break;
  213.     default: break;
  214.     }
  215.     return 0;
  216. }
  217. static const int kTooltipMaxLines = 5;
  218. static const int kMaxSeqInTooltip = 20;
  219. string  CAlnVecRow::GetTooltip(EColumnType col_type, CGlPane& pane)
  220. {
  221.     switch(col_type) {
  222.     case eIcons: return x_GetIconsTooltip(pane);
  223.     case eStart: return "First visible position in sequence coordinates";
  224.     case eAlignment:    return x_GetAlignmentTooltip(pane);
  225.     case eEnd: return "Last visible position in sequence coordinates";
  226.     case eSeqEnd: return "Last position in sequence";
  227.     default: break;
  228.     }
  229.     return "";
  230. }
  231. string  CAlnVecRow::x_GetIconsTooltip(CGlPane& pane)
  232. {
  233.     _ASSERT(x_GetHost());
  234.     string s_tip;
  235.     TVPPoint pt = x_GetHost()->ARH_GetVPMousePos();
  236.     TVPRect rc_btn = x_GetButtonRect(pane, eExpand);
  237.     if(rc_btn.PtInRect(pt)) {
  238.         if(IsExpandable())    {
  239.             s_tip = "Click to ";
  240.             s_tip += m_bExpanded ? "collapse" : "expand";
  241.         } else {
  242.             s_tip = "Nothing to expand";
  243.         }
  244.     } else {
  245.         rc_btn = x_GetButtonRect(pane, eSetupGraphs);
  246.         if(rc_btn.PtInRect(pt)) {
  247.             s_tip = "Setup Graphs";
  248.         }
  249.     }
  250.     return s_tip;
  251. }
  252. #define TOOLTIP_RANGE_PIX 3
  253. inline  void    glLined(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2)
  254. {
  255.     glVertex2d(x1, y1);
  256.     glVertex2d(x2, y2);
  257. }
  258. string  FormatRange(TSignedSeqPos from, TSignedSeqPos to)
  259. {
  260.     string s =  NStr::IntToString(to + 1);
  261.     s += "-";
  262.     s += NStr::IntToString(to + 1);
  263.     return s;
  264. }
  265. string  CAlnVecRow::x_GetAlignmentTooltip(CGlPane& pane)
  266. {
  267.     pane.OpenOrtho();
  268.     pane.Close();
  269.     double w_x = pane.UnProjectX(Fl::event_x());
  270.     double pix_w = pane.UnProjectWidth(TOOLTIP_RANGE_PIX);
  271.     // append Name and Position
  272.     string s_tip = m_Text;
  273.     if(m_Handle.IsNegativeStrand())
  274.         s_tip += ", Negative Strand";
  275.     TSeqPos pos = (TSeqPos) w_x;
  276.     s_tip += string("nPos ") + NStr::IntToString(pos + 1);
  277.     TSignedSeqPos seq_pos = m_Handle.GetSeqPosFromAlnPos(pos);
  278.     if(seq_pos >= 0)    {
  279.         s_tip += ", on Sequence ";
  280.         s_tip += NStr::IntToString(seq_pos + 1);
  281.     }
  282.     // Append information on gaps and inserts
  283.     TSeqPos start = (TSeqPos) floor(w_x - pix_w / 2);
  284.     TSeqPos end = (TSeqPos) ceil(w_x + pix_w / 2);
  285.     CAlnMap::TSignedRange range(start, end);
  286.     // obtain chunks in the range [start, end]
  287.     CRef<CAlnVec::CAlnChunkVec> v_chunks =  m_Handle.GetAlnChunks(range,
  288.                       CAlnVec::fAllChunks | CAlnVec::fDoNotTruncateSegs);
  289.     int chunks_n = min((int) v_chunks->size(), kTooltipMaxLines);
  290.     if(chunks_n)   { // show chunks tooltip
  291.         string seq;
  292.         for (int i = 0;  i < chunks_n;  i++) {
  293.             CConstRef<CAlnMap::CAlnChunk> chunk = (*v_chunks)[i];
  294.             CAlnMap::TSegTypeFlags type  = chunk->GetType();
  295.             const TSignedSeqRange& aln_r = chunk->GetAlnRange();
  296.             const TSignedSeqRange& seq_r = chunk->GetRange();
  297.             if((type & CAlnMap::fSeq)  &&  (type & CAlnMap::fNotAlignedToSeqOnAnchor))  { //insert
  298.                 //generate string for sequence
  299.                 TSeqRange seq_r(chunk->GetRange().GetFrom(), chunk->GetRange().GetTo());
  300.                 bool b_ellipsis = false;
  301.                 if((int) seq_r.GetLength() > kMaxSeqInTooltip)    { // to long to be displayed
  302.                     seq_r.SetToOpen(seq_r.GetFrom() + kMaxSeqInTooltip);
  303.                     b_ellipsis = true;
  304.                 }
  305.                 m_Handle.GetSeqString(seq, seq_r);
  306.                 if(b_ellipsis)
  307.                     seq += "...";
  308.                 // generate a string for the chunk
  309.                 TSeqPos aln_left = aln_r.GetToOpen(); // a bit of hack
  310.                 s_tip += "nInsert ";
  311.                 s_tip += FormatRange(aln_left, aln_left + 1);
  312.                 s_tip += ", on Sequence ";
  313.                 s_tip += FormatRange(seq_r.GetFrom(), seq_r.GetTo() + 1);
  314.                 s_tip += " : ";
  315.                 s_tip += seq;
  316.             }   else if(type == 0)   {
  317.                 // generate string for gap
  318.                 s_tip += "nGap ";
  319.                 s_tip += FormatRange(aln_r.GetFrom() + 1, aln_r.GetTo() + 1);
  320.                 s_tip += ", on Sequence ";
  321.                 s_tip += FormatRange(seq_r.GetFrom() + 1, seq_r.GetTo() + 1);
  322.             }
  323.         }
  324.     }
  325.     return s_tip;
  326. }
  327. void    CAlnVecRow::x_OnClickExpandBtn()
  328. {
  329.     fl_cursor(FL_CURSOR_WAIT);
  330.     Expand(! IsExpanded());
  331.     fl_cursor(FL_CURSOR_DEFAULT);
  332. }
  333. /// Renders graphical part of the row
  334. void    CAlnVecRow::x_RenderAlign(CGlPane& pane)
  335. {
  336.     _ASSERT(m_pStyle);
  337.     pane.OpenOrtho();
  338.     TModelUnit offset_x = pane.GetOffsetX();
  339.     TModelUnit offset_y = pane.GetOffsetY();
  340.     TModelRect rc_lim = pane.GetModelLimitsRect();
  341.     TModelRect rc_model = pane.GetVisibleRect();
  342.     TModelUnit y2 = rc_lim.Top() + kAlignSpace - offset_y;
  343.     TModelUnit y1 = rc_lim.Top() + m_BaseHeight -1 - kAlignSpace - offset_y;
  344.     TSeqPos row_start = m_Handle.GetSeqAlnStart();
  345.     TSeqPos row_stop = m_Handle.GetSeqAlnStop();
  346.     glLineWidth(1.0f);
  347.     glColorC(m_pStyle->GetAlignColor());
  348.     // now render segments actually present
  349.     unsigned Left = (unsigned) floor(rc_model.Left());
  350.     unsigned Right = (unsigned) ceil(rc_model.Right());
  351.     CAlnMap::TSignedRange Range(Left, Right);
  352.     // render aligned segments
  353.     CRef<CAlnVec::CAlnChunkVec> vAlnChunks = m_Handle.GetAlnChunks(Range, CAlnVec::fSkipInserts);
  354.     if(m_pCache)    { // render parts of chunks accordingly to scores
  355.         pane.Close();
  356.         x_RenderAlignScores(pane, vAlnChunks);
  357.         pane.OpenOrtho();
  358.     } else { // scores are not available - render all chunks with a default color
  359.         // render a single line for all possible gaps
  360.         TModelUnit Yc = (y2 + y1) / 2;
  361.         glBegin(GL_LINES);
  362.         glLined(row_start - offset_x, Yc, row_stop - offset_x, Yc);
  363.         glEnd();
  364.         x_RenderAlignSegments(pane, vAlnChunks, (int) y1, (int) y2);
  365.     }
  366.     // render inserts
  367.     CRef<CAlnVec::CAlnChunkVec> vChunks = m_Handle.GetAlnChunks(Range, CAlnVec::fInsertsOnly);
  368.     glColor3d(0, 0, 0.5);
  369.     glBegin(GL_LINES);
  370.     for (int i = 0;  i < vChunks->size();  i++) {
  371.         CConstRef<CAlnMap::CAlnChunk> chunk = (*vChunks)[i];
  372.         _ASSERT(chunk->GetType() & CAlnMap::fSeq);
  373.         _ASSERT(chunk->GetType() & CAlnMap::fNotAlignedToSeqOnAnchor);
  374.         TModelUnit ins_pos = chunk->GetAlnRange().GetFrom() - offset_x;
  375.         TModelUnit len = chunk->GetRange().GetLength();
  376.         TModelUnit x1 = ins_pos - len / 2;
  377.         TModelUnit x2 = x1 + len;
  378.         // assuming glBegin(GL_LINES)
  379.         glLined(ins_pos, y1, ins_pos, y2);
  380.         glLined(x1, y1, x2, y1);
  381.         glLined(x1, y2, x2, y2);
  382.     }
  383.     glEnd();
  384.     // render sequence if its visible
  385.     if(x_CanRenderSeq(pane))
  386.     {
  387.         double H = m_pStyle->GetSeqFont().TextHeight();
  388.         double y = floor((y1 + y2 + H) / 2);
  389.         x_RenderSequence(pane, y, Left, Right);
  390.     }
  391.     pane.Close();
  392.     x_RenderGraph(pane, vAlnChunks);
  393. }
  394. void    CAlnVecRow::x_RenderAlignSegments(CGlPane& pane, TRefChunks& chunks, int top_y, int bottom_y)
  395. {
  396.     glColorC(m_pStyle->GetAlignColor());
  397.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  398.     TModelUnit offset_x = pane.GetOffsetX();
  399.     for (int i = 0;  i < chunks->size();  i++) {
  400.         CConstRef<CAlnMap::CAlnChunk> chunk = (*chunks)[i];
  401.         if((chunk->GetType() & CAlnMap::fSeq))  {
  402.             _ASSERT((chunk->GetType() & CAlnMap::fNotAlignedToSeqOnAnchor) == 0);
  403.             const TSignedSeqRange& R = chunk->GetAlnRange();
  404.             glRectd(R.GetFrom() - offset_x, top_y,
  405.                     R.GetToOpen() - offset_x, bottom_y);
  406.         }
  407.     }
  408. }
  409. /// Renders alignment (graphical) part of the row according to scores.
  410. /// Score intervals are rendered differently depending on their size.
  411. /// Long intervals ("long" meaning covering more than one full pixel) are rendered in
  412. /// "vector" mode - the series of pixels corresponding to a single interval
  413. /// is drawn as a single rectangle with color defined by the intreval's score.
  414. /// Short intervals are rendered in "raster" mode - algorithm iterates by intervals
  415. /// and calculates average and maximal scores corresponding to a particular pixel,
  416. /// then each pixel is drawn with its individual color.
  417. void    CAlnVecRow::x_RenderAlignScores(CGlPane& pane, TRefChunks& chunks)
  418. {
  419.     pane.OpenPixels();
  420.     const TVPRect& rc_vp = pane.GetViewport();
  421.     const TModelRect rc_vis = pane.GetVisibleRect();
  422.     glTranslated(0.0, rc_vp.Top(), 0.0); // to make the display list "scrollable" vertically
  423.     // if horz projection has changed - invalidate display list
  424.     if(m_PixLeft != rc_vp.Left()  ||  m_PixRight != rc_vp.Right()
  425.         ||  m_ModelLeft != rc_vis.Left()  ||  m_ModelRight != rc_vis.Right())    {
  426.         m_DList.Invalidate();
  427.         m_PixLeft = rc_vp.Left();
  428.         m_PixRight = rc_vp.Right();
  429.         m_ModelLeft = rc_vis.Left();
  430.         m_ModelRight = rc_vis.Right();
  431.     }
  432.     if(m_DList.IsValid())   {
  433.         m_DList.Call();
  434.     } else { // need to create a new one
  435.         m_DList.Begin(GL_COMPILE_AND_EXECUTE);
  436.         TModelUnit  left = rc_vis.Left();
  437.         TModelUnit  scale_x = pane.GetScaleX();
  438.         int range_pix_start = rc_vp.Left();
  439.         int range_pix_end = rc_vp.Right();
  440.         // visible alignment range in seq coords
  441.         int range_from = (int) (floor(left));
  442.         // int range_to_open = (int) (ceil(pane.GetVisibleRect().Right()));
  443.         int top_y = - kAlignSpace;
  444.         int bottom_y = - m_BaseHeight + kAlignSpace;
  445.         int off_y = 0, extr_off_y = 0;
  446.         // obtain Score Collection and setup iterators
  447.         const CScoreCache::TScoreColl& ScoreColl = m_pCache->GetScores(m_Handle.GetRowNum());
  448.         CScoreCache::TScoreColl::const_iterator it = ScoreColl.begin();
  449.         const CScoreCache::TScoreColl::const_iterator it_end = ScoreColl.end();
  450.         it = ScoreColl.find(it, it_end, range_from);
  451.         double int_score;
  452.         double  pix_start, pix_end;
  453.         double  score_sum = 0, score_min = 0, score_len = 0;
  454.         bool    b_first = true;     // "true" if pixel is being processed for the first time
  455.         bool    b_new_interval = true;
  456.         bool b_lines = true;
  457.         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  458.         glBegin(GL_LINES);
  459.         int i_prev_chunk = -1, i_chunk = 0, n_chunks = chunks->size();
  460.         CConstRef<CAlnMap::CAlnChunk> chunk;
  461.         // [pos_start, pos_end) defines range being processed
  462.         int pos_start = -1, pos_end = range_from;
  463.         bool b_skip  = false;
  464.         // iterate by pixels, score intervals and chunks
  465.         for( int pix = range_pix_start;
  466.              pix <= range_pix_end  &&  it != it_end  &&  i_chunk < n_chunks;  )
  467.         {
  468.             if(i_prev_chunk != i_chunk) {
  469.                 chunk = (*chunks)[i_chunk];
  470.                 int type = chunk->GetType();
  471.                 b_skip = false;
  472.                 if(type & CAlnMap::fSeq)    { // aligned segment
  473.                     off_y = 0;
  474.                     extr_off_y = kExtremeArea;
  475.                 } else if(type & (CAlnVec::fNoSeqOnRight | CAlnVec::fNoSeqOnLeft))    {
  476.                     // empty space - do not draw anything
  477.                     b_skip = true;
  478.                 } else { // gap
  479.                     off_y =  kGapOffset ;
  480.                     extr_off_y = kGapOffset + kGapExtremeArea;
  481.                 }
  482.             }
  483.             if(b_new_interval)    { // new range
  484.                 int_score = it->GetAttr();
  485.             }
  486.             if(i_chunk != i_prev_chunk  ||  b_new_interval) {
  487.                 // [pos_start, pos_end) is defined as intersection of current score interval
  488.                 // and current chunk
  489.                 pos_start = pos_end;
  490.                 pos_end = min((int) chunk->GetAlnRange().GetToOpen(), (int) it->GetToOpen());
  491.                 // transform from seq. coords to pixels
  492.                 pix_start = range_pix_start + ((double) (pos_start - left)) / scale_x;
  493.                 pix_end = range_pix_start + ((double) (pos_end - left)) / scale_x;
  494.                 i_prev_chunk = i_chunk;
  495.                 b_new_interval = false;
  496.             }
  497.             if(b_skip  &&  (pix_start <= pix  &&  pix_end >= pix + 1))    {
  498.                 int strip_end = (int) ceil(pix_end) - 1;
  499.                 if(! b_skip)    {
  500.                 if(b_lines) {
  501.                     glEnd();
  502.                     b_lines = false;
  503.                 }
  504.                 // interval covers current pixel and may be consequent pixels
  505.                 // draw them in one iteration
  506.                 glColorC(m_pCache->GetColorForScore(int_score));
  507.                 glRectd(pix, top_y - off_y, strip_end, bottom_y + off_y);
  508.                 }
  509.                 pix = strip_end;
  510.                 b_first = true;
  511.             }
  512.             //[start, end] specify part of the pixel covered by current score interval
  513.             double start = max((double) pix, pix_start);
  514.             double end = min((double) pix + 1, pix_end);
  515.             double len = end - start;
  516.             _ASSERT(len >= 0.0  && len <= 1.0);
  517.             double d_score = len * int_score;
  518.             if(b_first) {  // new pixel - reset assign values to accumulators
  519.                 score_min = int_score;
  520.                 score_sum = d_score;
  521.                 score_len = len;
  522.                 b_first = false;
  523.             } else { // accumulate
  524.                 score_min = min(score_min, int_score);
  525.                 score_sum += d_score;
  526.                 score_len += len;
  527.             }
  528.             if(pix_end < pix + 1)    {  // current range ends before current pixel
  529.                 if(it->GetToOpen() <= pos_end)  { // advance score interval
  530.                     it++;
  531.                     b_new_interval = true;
  532.                 }
  533.                 if(chunk->GetAlnRange().GetToOpen() <= pos_end)  { // advance chunk
  534.                     i_chunk++;
  535.                 }
  536.             } else { // pixel is fully covered with current range - draw the pixel
  537.                 if(! b_lines)   {
  538.                     glBegin(GL_LINES);
  539.                     b_lines = true;
  540.                 }
  541.                 double sc = score_sum / score_len;
  542.                 bool b_diff = (score_min != sc);
  543.                 glColorC(m_pCache->GetColorForScore(b_diff ? score_min : sc));
  544.                 glLined(pix, top_y - off_y, pix, bottom_y + off_y);
  545.                 if(b_diff) {
  546.                     glColorC(m_pCache->GetColorForScore(sc));
  547.                     glLined(pix, top_y - extr_off_y, pix, bottom_y + extr_off_y);
  548.                 }
  549.                 pix++;
  550.                 b_first = true;
  551.             }
  552.         }
  553.         if(b_lines) {
  554.             glEnd();
  555.         }
  556.         m_DList.End();
  557.     }
  558.     glTranslated(0.0, -rc_vp.Top(), 0.0);
  559.     pane.Close();
  560. }
  561. #define SEQ_OFF_VERT 0
  562. #define SEQ_OFF_HORZ 0
  563. /// Checks if sequence can be drawn.
  564. bool CAlnVecRow::x_CanRenderSeq(CGlPane& pane)
  565. {
  566.     if(m_pStyle)    {
  567.         double min_w = 1.0 / m_pStyle->GetSeqFont().GetMetric(CGlBitmapFont::eMetric_MaxCharWidth);
  568.         double scale_x = pane.GetScaleX();
  569.         return min_w >= scale_x;
  570.     } else return false;
  571. }
  572. // renders a row of seq symbols in the range [Start, Stop]
  573. void CAlnVecRow::x_RenderSequence(CGlPane& pane, float y, int start, int stop)
  574. {
  575.     _ASSERT(m_pStyle);
  576.     string seq;
  577.     m_Handle.GetAlnSeqString(seq, CAlnVec::TSignedRange(start, stop));
  578.     replace(seq.begin(), seq.end(), '-', ' ');
  579.     glColorC(m_pStyle->GetAlignTextColor());
  580.     float x = start + 0.5 - pane.GetOffsetX();
  581.     m_pStyle->GetSeqFont().ArrayTextOut(x, y, 1.0f, 0.0f, seq.c_str(),
  582.                              (float) pane.GetScaleX(), 0.0f);
  583. }
  584. static const int kTextOffsetY = 0;
  585. static const int kTextOffsetX = 2;
  586. static const int kPosOffsetX = 4;
  587. void    CAlnVecRow::x_RenderDescr(CGlPane& pane, int state)
  588. {
  589.     _ASSERT(m_pStyle);
  590.     pane.OpenPixels();
  591.     TVPRect rc_vp = pane.GetViewport();
  592.     bool b_wid_focused = (state & fWidgetFocused) != 0;
  593.     //draw background
  594.     if(state & fItemSelected) {
  595.         if(b_wid_focused)   {
  596.             glColorC(m_pStyle->GetSelBackFocusedColor());
  597.         } else {
  598.             glColorC(m_pStyle->GetSelBackColor());
  599.         }
  600.         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  601.         glRectd(rc_vp.Left(), rc_vp.Bottom() - 1, rc_vp.Right(), rc_vp.Top());
  602.     }
  603.     // draw text label
  604.     glColorC((state & fItemSelected) != 0 ? m_pStyle->GetSelTextColor()
  605.                                           : m_pStyle->GetTextColor());
  606.     int x = rc_vp.Left() + kTextOffsetX;
  607.     int w = rc_vp.Width() - kTextOffsetX;
  608.     m_pStyle->GetTextFont().TextOut(x, rc_vp.Top() - m_BaseHeight + 1, w,
  609.                             m_BaseHeight, m_Text.c_str(), FL_ALIGN_LEFT);
  610.     // draw focus frame
  611.     if(b_wid_focused  &&  (state & fItemFocused) != 0) {
  612.         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  613.         glBegin(GL_LINE_LOOP);
  614.             glVertex2d(rc_vp.Left(), rc_vp.Bottom());
  615.             glVertex2d(rc_vp.Right(), rc_vp.Bottom());
  616.             glVertex2d(rc_vp.Right(), rc_vp.Top());
  617.             glVertex2d(rc_vp.Left(), rc_vp.Top());
  618.         glEnd();
  619.     }
  620.     pane.Close();
  621. }
  622. void    CAlnVecRow::x_RenderGraph(CGlPane& pane, CConstRef<CAlnVec::CAlnChunkVec> chunks)
  623. {
  624.     if(m_bExpanded) {
  625.         if( m_pGraph  && m_pGraph->IsCreated())   {
  626.             TModelUnit offset_y = pane.GetOffsetY();
  627.             int y = (int) (pane.GetVisibleRect().Top() - offset_y) + m_BaseHeight;
  628.             int h = m_Height - m_BaseHeight;
  629.             m_pGraph->Render(pane, y, h, chunks);
  630.         } else _ASSERT(false);
  631.     }
  632. }
  633. const static int kButtonOffset = 2;
  634. const static int kButtonSize = 11;
  635. const static int kButtonSignSize = 7;
  636. /// Returns buttons bounds in screen coordinates, "pane" parameter specifies CGlPane
  637. /// corresponding to "Icons" column
  638. TVPRect CAlnVecRow::x_GetButtonRect(CGlPane& pane, EButtons btn)
  639. {
  640.     const TVPRect& rc_vp = pane.GetViewport();
  641.     int btn_space = kButtonSize + kButtonOffset;
  642.     int x = rc_vp.Left() + kButtonOffset + ((int) btn) * btn_space;
  643.     int y_top = rc_vp.Top() - (m_BaseHeight - kButtonSize) / 2;// kButtonOffset;
  644.     TVPRect rc(x, y_top - kButtonSize + 1, x + kButtonSize - 1, y_top);
  645.     return rc;
  646. }
  647. void    CAlnVecRow::x_RenderIcons(CGlPane& pane)
  648. {
  649.     _ASSERT(m_pStyle);
  650.     pane.OpenPixels();
  651.     
  652.     glColorC(m_pStyle->GetTextColor());
  653.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  654.     // draw "Expand" button
  655.     TVPRect rc_btn = x_GetButtonRect(pane, eExpand);
  656.     glRectd(rc_btn.Left(), rc_btn.Bottom(), rc_btn.Right(), rc_btn.Top());
  657.     if(IsExpandable())    {
  658.         int offset = (kButtonSize - kButtonSignSize) / 2;
  659.         TVPPoint pt_c = rc_btn.CenterPoint();
  660.         // render "+" or "-"
  661.         glBegin(GL_LINES);
  662.             glVertex2d(rc_btn.Left() + offset, pt_c.Y());
  663.             glVertex2d(rc_btn.Left() + offset + kButtonSignSize, pt_c.Y());
  664.             if(! m_bExpanded)   {
  665.                 glVertex2d(pt_c.X(), rc_btn.Bottom() + offset);
  666.                 glVertex2d(pt_c.X(), rc_btn.Bottom() + offset + kButtonSignSize);
  667.             }
  668.         glEnd();
  669.     }
  670.     if(m_pGraph  &&  m_pGraph->HasData())   {   // draw "Graph" button
  671.         rc_btn = x_GetButtonRect(pane, eSetupGraphs);
  672.         glRectd(rc_btn.Left(), rc_btn.Bottom(), rc_btn.Right(), rc_btn.Top());
  673.         m_pStyle->GetTextFont().TextOut(rc_btn.Left() + 1, rc_btn.Bottom() + 1,
  674.                                         kButtonSize - 2, kButtonSize - 2, "...", FL_ALIGN_CENTER);
  675.     }
  676.     // draw strand marker
  677.     rc_btn = x_GetButtonRect(pane, eStrandMarker);
  678.     int y_c = rc_btn.CenterPoint().Y();
  679.     int half = rc_btn.Height() / 2;
  680.     int x1 = rc_btn.Left();
  681.     int x2 = rc_btn.Right();
  682.     if(m_Handle.IsNegativeStrand()) {
  683.         swap(x1, x2);
  684.     }
  685.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  686.     glColor3d(0.0, 0.5, 0.0);
  687.     glBegin(GL_POLYGON);
  688.         glVertex2d(x1, y_c - half);
  689.         glVertex2d(x2, y_c);
  690.         glVertex2d(x1, y_c + half);
  691.     glEnd();
  692.     pane.Close();
  693. }
  694. void    CAlnVecRow::x_RenderStartPos(CGlPane& pane)
  695. {
  696.     const TModelRect& rc_v = pane.GetVisibleRect();
  697.     int aln_pos = (int) floor(rc_v.Left());
  698.     x_RenderAlnPos(pane, aln_pos, CAlnVec::eRight);
  699. }
  700. void    CAlnVecRow::x_RenderEndPos(CGlPane& pane)
  701. {
  702.     const TModelRect& rc_v = pane.GetVisibleRect();
  703.     int aln_pos = -1 + (int) ceil(rc_v.Right());
  704.     x_RenderAlnPos(pane, aln_pos, CAlnVec::eLeft);
  705. }
  706. void    CAlnVecRow::x_RenderSeqEnd(CGlPane& pane)
  707. {
  708.     TSeqPos pos = m_Handle.GetBioseqHandle().GetBioseqLength() -1;
  709.     x_RenderPos(pane, pos, "");
  710. }
  711. // generates text label for given position in alignment
  712. void    CAlnVecRow::x_RenderAlnPos(CGlPane& pane, TSeqPos aln_pos, CAlnVec::ESearchDirection dir)
  713. {
  714.     char *s_marker = "";
  715.     int seq_pos = m_Handle.GetSeqPosFromAlnPos(aln_pos);
  716.     if(seq_pos == -1)   {
  717.         seq_pos = m_Handle.GetSeqPosFromAlnPos(aln_pos, dir);
  718.         switch(dir) {
  719.         case CAlnVec::eRight:  s_marker = ">>  "; break;
  720.         case CAlnVec::eLeft:  s_marker = "<<  "; break;
  721.         default: break;
  722.         }
  723.     }
  724.     x_RenderPos(pane, seq_pos, s_marker);
  725. }
  726. void    CAlnVecRow::x_RenderPos(CGlPane& pane, TSeqPos pos, const char* s_marker)
  727. {
  728.     _ASSERT(m_pStyle);
  729.     pane.OpenPixels();
  730.     const TVPRect& rc_vp = pane.GetViewport();
  731.     // draw box
  732.     glColorC(m_pStyle->GetFrameColor());
  733.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  734.     glRectd(rc_vp.Left(), rc_vp.Bottom(), rc_vp.Right(), rc_vp.Top() + 1);
  735.     string s_num = CTextUtils::FormatSeparatedNumber(pos + 1);
  736.     string s_label(s_marker);
  737.     s_label += s_num;
  738.     glColorC(m_pStyle->GetTextColor());
  739.     int x = rc_vp.Left() + kTextOffsetX;
  740.     int w = rc_vp.Width() - kTextOffsetX * 3;
  741.     m_pStyle->GetTextFont().TextOut(x, rc_vp.Top() - m_BaseHeight + 1, w, m_BaseHeight,
  742.                             s_label.c_str(), FL_ALIGN_RIGHT);
  743.     pane.Close();
  744. }
  745. void    CAlnVecRow::x_RenderEmptyBox(CGlPane& pane)
  746. {
  747.     pane.OpenPixels();
  748.     glColorC(m_pStyle->GetFrameColor());
  749.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  750.     TVPRect rc_vp = pane.GetViewport();
  751.     glRectd(rc_vp.Left(), rc_vp.Bottom(), rc_vp.Right(), rc_vp.Top());
  752.     pane.Close();
  753. }
  754. bool    CAlnVecRow::IsExpandable() const
  755. {
  756.     return m_pGraph->HasData();
  757. }
  758. bool    CAlnVecRow::IsExpanded() const
  759. {
  760.     return m_bExpanded;
  761. }
  762. void    CAlnVecRow::Expand(bool b_exp)
  763. {
  764.     if(IsExpandable()  &&  IsExpanded() != b_exp)   {
  765.         m_bExpanded = b_exp;
  766.         m_Height = m_BaseHeight;
  767.         if(m_bExpanded) {
  768.             x_CreateGraph();
  769.             if(m_pGraph  &&  m_pGraph->IsCreated())  {
  770.                 m_Height += m_pGraph->GetPreferredHeight();
  771.             }
  772.         } else x_DestroyGraph();
  773.         if (x_GetHost()) {
  774.             x_GetHost()->ARH_OnRowChanged(this);
  775.         }
  776.     }
  777. }
  778. const IAlnRowGraphProperties*     CAlnVecRow::GetProperties() const
  779. {
  780.     return m_pGraph ? m_pGraph->GetProperties() : NULL;
  781. }
  782. void    CAlnVecRow::SetProperties(IAlnRowGraphProperties* props)
  783. {
  784.     if(m_pGraph)   {
  785.         m_pGraph->SetProperties(props);
  786.     }
  787. }
  788. END_NCBI_SCOPE
  789. /*
  790.  * ===========================================================================
  791.  * $Log: align_row.cpp,v $
  792.  * Revision 1000.5  2004/06/01 21:07:00  gouriano
  793.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.41
  794.  *
  795.  * Revision 1.41  2004/05/21 22:27:52  gorelenk
  796.  * Added PCH ncbi_pch.hpp
  797.  *
  798.  * Revision 1.40  2004/05/10 17:46:35  yazhuk
  799.  * Addressed GCC warnings
  800.  *
  801.  * Revision 1.39  2004/04/06 19:07:35  yazhuk
  802.  * Added "EColumnType col_type" argument to GetHTMLActiveAreas(), added generation
  803.  * of CHTMLActiveAreas for graphics in alignment
  804.  *
  805.  * Revision 1.38  2004/04/06 16:06:32  yazhuk
  806.  * Removed _ASSERT from RenderColumn()
  807.  *
  808.  * Revision 1.37  2004/04/06 13:34:04  dicuccio
  809.  * Formatting changes - trimmed trailing white space off of lines
  810.  *
  811.  * Revision 1.36  2004/04/02 17:13:31  yazhuk
  812.  * Removed dumplicate 'const'
  813.  *
  814.  * Revision 1.35  2004/04/02 16:41:07  yazhuk
  815.  * Rendering of strand indicator, clean-up
  816.  *
  817.  * Revision 1.34  2004/03/29 19:09:18  yazhuk
  818.  * Added API for Graph properties access, CHTMLActiveArea-s generation,
  819.  * eliminated m_TraceProxy
  820.  *
  821.  * Revision 1.33  2004/03/26 15:01:59  yazhuk
  822.  * CTraceDataProxy  class added
  823.  *
  824.  * Revision 1.32  2004/03/25 13:05:49  dicuccio
  825.  * Use _TRACE() instead of cout
  826.  *
  827.  * Revision 1.31  2004/03/24 19:21:49  yazhuk
  828.  * Lots of changes in data loading, tooltips.
  829.  *
  830.  * Revision 1.30  2004/03/18 17:10:19  yazhuk
  831.  * Added API for expanding rows
  832.  *
  833.  * Revision 1.29  2004/03/16 15:37:22  vasilche
  834.  * Added required include
  835.  *
  836.  * Revision 1.28  2004/03/11 17:50:41  dicuccio
  837.  * Updated typedefs: dropped TDimension, TPosition, TIndex, TColor; use TSeqRange
  838.  * instead of TRange
  839.  *
  840.  * Revision 1.27  2004/03/08 17:07:31  yazhuk
  841.  * Replaced CTraceGraph with IAlnVecRowGraph interface; clean-up
  842.  *
  843.  * Revision 1.26  2004/03/08 15:44:23  yazhuk
  844.  * Implemented creation of Trace Graphs from CSeq_graphs, refactored tooltips
  845.  * generation and rendering
  846.  *
  847.  * Revision 1.25  2004/03/05 17:39:14  dicuccio
  848.  * Use sequence::Getid() instead of CSeq_id::GetStringDescr()
  849.  *
  850.  * Revision 1.24  2004/03/02 15:12:21  yazhuk
  851.  * Added support for Trace Graphs
  852.  *
  853.  * Revision 1.23  2004/02/17 15:19:10  yazhuk
  854.  * Support for graphics caching
  855.  *
  856.  * Revision 1.22  2004/02/10 19:54:51  yazhuk
  857.  * Redesigned alignment rendering, implemented scores averaging
  858.  *
  859.  * Revision 1.21  2004/01/08 19:44:04  yazhuk
  860.  * Extended tooltips support
  861.  *
  862.  * Revision 1.20  2003/12/29 23:21:07  yazhuk
  863.  * Added GetTooltip()
  864.  *
  865.  * Revision 1.19  2003/12/18 21:10:27  yazhuk
  866.  * Redesigned CAlnVecRow - separated display style
  867.  *
  868.  * Revision 1.18  2003/12/08 15:15:45  yazhuk
  869.  * Implemented workaround for OpenGL precision problems.
  870.  *
  871.  * Revision 1.17  2003/12/01 17:00:44  yazhuk
  872.  * Migrated to using CGUIEvent
  873.  *
  874.  * Revision 1.16  2003/11/17 21:18:51  yazhuk
  875.  * Refactored sequence rendering, replaced TextOut() with ArrayTextOut
  876.  *
  877.  * Revision 1.15  2003/11/03 16:50:41  yazhuk
  878.  * Implemented event handling and support for expanding/collapsing alignment rows
  879.  *
  880.  * Revision 1.14  2003/10/29 23:33:23  yazhuk
  881.  * Migrated to new classes, did a lot of refactoring
  882.  *
  883.  * Revision 1.13  2003/10/20 15:52:47  yazhuk
  884.  * Changed colors.
  885.  *
  886.  * Revision 1.12  2003/10/15 21:27:07  yazhuk
  887.  * Migrated from using CAlnVec to accessing data via "generic" interface in CAlignDataSource.
  888.  *
  889.  * Revision 1.11  2003/10/10 19:05:58  yazhuk
  890.  * Implemented score coloring
  891.  *
  892.  * Revision 1.10  2003/10/08 14:17:25  dicuccio
  893.  * use glColor3fv instead of glColorC
  894.  *
  895.  * Revision 1.9  2003/10/03 16:31:17  yazhuk
  896.  * Fixed bug with closing CGlPane
  897.  *
  898.  * Revision 1.8  2003/09/29 13:44:46  yazhuk
  899.  * Added "SeqEnd" column and functions for rendering "Start", "End" and "SeqEnd" columns
  900.  *
  901.  * Revision 1.7  2003/09/23 21:59:49  yazhuk
  902.  * Changed color and adjusted text output position
  903.  *
  904.  * Revision 1.6  2003/09/14 14:03:44  ucko
  905.  * #include <math.h> (needed with GCC)
  906.  *
  907.  * Revision 1.5  2003/09/10 20:39:04  yazhuk
  908.  * Introduced notion of Columns
  909.  *
  910.  * Revision 1.4  2003/09/08 20:48:48  yazhuk
  911.  * Suppressed "-" drawing for gaps
  912.  *
  913.  * Revision 1.3  2003/09/08 16:22:13  yazhuk
  914.  * Drawing insertions, small improvements
  915.  *
  916.  * Revision 1.2  2003/09/02 16:53:57  yazhuk
  917.  * GCC compilation fixes
  918.  *
  919.  * Revision 1.1  2003/08/28 18:25:28  yazhuk
  920.  * Initial revision
  921.  *
  922.  * ===========================================================================
  923.  */