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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ruler.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 21:10:43  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ruler.cpp,v 1000.4 2004/06/01 21:10:43 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 <gui/opengl/glhelpers.hpp>
  42. #include <gui/widgets/gl/ruler.hpp>
  43. #include <math.h>
  44. BEGIN_NCBI_SCOPE
  45. CRuler::CRuler(bool b_horz)
  46. :   m_bHorz(b_horz),
  47.     m_bAutoRange(true),
  48.     m_Start(0),
  49.     m_End(0),
  50.     m_Offset(0),
  51.     m_bReverseDisplay(false),
  52.     m_DisplayOptions(0),
  53.     m_Font(CGlBitmapFont::eHelvetica12),
  54.     m_TextColor(0.2f, 0.4f, 0.2f),
  55.     m_RullerColor(0.2f, 0.2f, 0.2f),
  56.     m_BackColor(0.95f, 0.95f, 0.95f),
  57.     m_MajorTickSize(6),
  58.     m_RegTickSize(3),
  59.     m_bDirty(true),
  60.     m_PosLabelsStep(-1)
  61. {
  62.     m_LabelPlace = m_bHorz ? eBottom : eLeft;
  63. }
  64. CRuler::~CRuler()
  65. {
  66. }
  67. void    CRuler::SetHorizontal(bool b_horz, ELabelPlacement place)
  68. {
  69.     m_bHorz = b_horz;
  70.     if(m_bHorz) {
  71.         switch(place)   {
  72.         case eLeft:
  73.         case eRight:    _ASSERT(false);
  74.         case eDefault: 
  75.         case eBottom: m_LabelPlace = eBottom; break;
  76.         case eTop: m_LabelPlace = eTop; break;
  77.         }
  78.     } else {
  79.         switch(place)   {
  80.         case eBottom:
  81.         case eTop:    _ASSERT(false);
  82.         case eDefault: 
  83.         case eLeft: m_LabelPlace = eLeft; break;
  84.         case eRight: m_LabelPlace = eRight; break;
  85.         }
  86.     }
  87.     m_bDirty = true;
  88. }
  89. void    CRuler::SetColor(EColorType type, const CGlColor& color)
  90. {
  91.     switch(type)    {
  92.     case eRuller: m_RullerColor = color; break;
  93.     case eText: m_TextColor = color; break;
  94.     case eBackground: m_BackColor = color; break;
  95.     default: _ASSERT(false);
  96.     }
  97.     m_bDirty = true;
  98. }
  99. void    CRuler::SetFont(CGlBitmapFont::EFont font_type)
  100. {
  101.     m_Font.SetFont(font_type);
  102.     m_bDirty = true;
  103. }
  104. void    CRuler::SetDisplayOptions(int options)
  105. {
  106.     m_DisplayOptions = options;
  107. }
  108. void    CRuler::SetAutoRange()
  109. {
  110.     m_bAutoRange = true;
  111.     m_Offset = 0;
  112.     m_bReverseDisplay = false;
  113. }
  114. void    CRuler::SetRange(int Start, int End, int SeqStart, bool b_reverse)
  115. {
  116.     m_bAutoRange = false;
  117.     m_Start = Start;
  118.     m_End = End;
  119.     m_Offset = SeqStart - (b_reverse ? 0 : m_Start);
  120.     m_bReverseDisplay = b_reverse;
  121. }
  122. void    CRuler::SetGeometryParam(EGeometryParam geom, int value)
  123. {
  124.     switch(geom)    {
  125.     case eRegularTickHeight: m_RegTickSize = value;    break;
  126.     case eMajorTickHeight: m_MajorTickSize = value;    break;
  127.     default: _ASSERT(false);
  128.     }
  129.     m_bDirty = true;
  130. }
  131. /// vertical spacing between text and borders or between text and other graphics
  132. static int  kTextSpaceY = 3; 
  133. TVPPoint     CRuler::GetPreferredSize() const
  134. {
  135.     int w = 0, h = 0;
  136.     if(m_bHorz) {
  137.         h = x_GetBaseHeight();
  138.         if(m_DisplayOptions & (fShowOrigin | fShowMetric))  {
  139.             double t_h = m_Font.GetMetric(CGlBitmapFont::eMetric_FullCharHeight);
  140.             int text_h = (int) ceil(t_h);
  141.             h += max(text_h, m_MajorTickSize) + kTextSpaceY;
  142.         }
  143.     } else {        
  144.     }
  145.     return TVPPoint(w, h);
  146. }
  147. TVPRect    CRuler::GetVPRect()
  148. {
  149.     TVPPoint pt = GetPreferredSize();
  150.     return TVPRect(0, 0, pt.X(), pt.Y());
  151. }
  152. TModelRect CRuler::GetModelRect()
  153. {
  154.     return TModelRect();
  155. }
  156. const static int kLabelSepX = 8;
  157. const static int kLabelSepY = 4;
  158. const static int kMinTickStepPixels = 5;
  159. const static int kLabelSepPix = 24; // min distance between labels
  160. // calculates distance in pixels between position labels
  161. void CRuler::x_CalculatePosLabelsStep(CGlPane& pane)
  162. {
  163.     m_MaxLabelH = m_Font.TextHeight();
  164.     double char_w = m_Font.GetMetric(CGlBitmapFont::eMetric_AvgCharWidth);            
  165.     double comma_w = m_Font.TextWidth(",");
  166.     
  167.     // determining maximal number of characters in a label
  168.     double max_num = max(x_ToDisplay(m_Start), x_ToDisplay(m_End));     
  169.     int digits_count = (int) ceil(log10(max_num));    
  170.     int commas_count = (digits_count - 1) / 3;
  171.     
  172.     // length of the longest possible label in pixels (add 2 for separation)
  173.     m_MaxLabelW = kLabelSepPix + digits_count * char_w + commas_count * comma_w; 
  174.     // calculate size of the longest label in model coords
  175.     double scale = m_bHorz ? pane.GetScaleX() : pane.GetScaleY();
  176.     double max_label_sym = 0;  // in symbols
  177.     if(m_bHorz) {        
  178.         max_label_sym = scale * m_MaxLabelW;
  179.         
  180.     } else {
  181.         max_label_sym = 2 * scale * m_MaxLabelH;
  182.     }
  183.     
  184.     // choosing step in model coords
  185.     double log = (max_label_sym >= 1.0) ? log10(max_label_sym) : 0;
  186.     log = ceil(log);
  187.     double step = pow((double)10, log);
  188.     double base_step = step;
  189.     if(step > 10.001)   {
  190.         // try to mimimize step without intersecting labels
  191.         if(m_bHorz)   {
  192.             // using compact notation (1 K vs 1,000) saves space, check if we can 
  193.             // benefit from this
  194.             // adjusting order
  195.             int groups_n = 0;
  196.             step = step * 10; // to compensate effect of fisrt iteration
  197.             double max_label_w = m_MaxLabelW;
  198.             do
  199.             {
  200.                 _ASSERT(step > 0);
  201.                 step = step / 10;
  202.                 log = ceil(log10(step));
  203.                 groups_n = (int) (log / 3);
  204.                 if(groups_n)  {
  205.                     int d_digits =  3 * groups_n - 2; 
  206.                     max_label_w = m_MaxLabelW - d_digits * char_w + groups_n * comma_w;
  207.                     max_label_sym = scale * max_label_w;
  208.                 }
  209.             } while(groups_n  &&  step > max_label_sym * 10);
  210.             m_MaxLabelW = max_label_w;
  211.             base_step = step;
  212.         }
  213.         // currently step has a form   10^X, lets check if we can choose
  214.         // a smaller step in a form  K * 10^(X-1), where K = 2, 5
  215.         // this adjusment does not affect labels size
  216.         if(step > max_label_sym * 5)    {
  217.             base_step = step / 10;  // 10^(X-1)
  218.             step = step / 5;        // 2 * 10^(X-1)
  219.         }
  220.         else if(step > max_label_sym * 2)   {
  221.             base_step = step / 10;  // 10^(X-1)
  222.             step = step / 2;        // 5 * 10^(X-1)          
  223.         }
  224.     }
  225.         
  226.     m_BaseStep = (int) base_step;
  227.     m_BaseStep = max(m_BaseStep, 1);
  228.     m_PosLabelsStep = (int) step;
  229.     m_PosLabelsStep  = max(m_PosLabelsStep , 1);
  230.     // choosing optimal distance between ticks
  231.     m_TickSpace = m_BaseStep;
  232.     int ar_K[] = { 10, 5 ,2 };
  233.     for( int i = 0; i < 3; i++ )    {
  234.         int space = m_TickSpace / ar_K[i];
  235.         if(space >= 1  &&  space / scale > kMinTickStepPixels)   {
  236.             m_TickSpace = space; 
  237.             break;
  238.         }
  239.     }
  240.     m_bDirty = false;
  241. }
  242. void  CRuler::Render(CGlPane& pane)
  243. {
  244.     CGlAttrGuard AttrGuard(GL_POLYGON_BIT | GL_LINE_BIT);
  245.     glLineWidth(1.0f);
  246.     const TModelRect& rc_lim = pane.GetModelLimitsRect();
  247.         
  248.     if(m_bAutoRange)    {
  249.         m_Start = (int) (m_bHorz ? rc_lim.Left() : rc_lim.Bottom());
  250.         m_End = (int) (m_bHorz ? rc_lim.Right() : rc_lim.Top()) - 1;
  251.     }
  252.     bool b_update = m_bDirty || m_PosLabelsStep <= 0;
  253.     if(! b_update)  {
  254.         bool b_scale_changed = m_bHorz ? (m_ScaleX != pane.GetScaleX())
  255.                                        : (m_ScaleY != pane.GetScaleY());
  256.         b_update =  b_scale_changed  ||  ! (m_rcLimits == rc_lim);
  257.         
  258.         m_rcLimits = rc_lim;
  259.         m_ScaleX = pane.GetScaleX();
  260.         m_ScaleY = pane.GetScaleY();
  261.     }
  262.     if(b_update)   
  263.         x_CalculatePosLabelsStep(pane);
  264.     
  265.     if(m_PosLabelsStep > 0) { // step is valid
  266.         // calculating range to draw
  267.         TModelRect rcV = pane.GetVisibleRect();
  268.         
  269.         // [first_elem, last_elem] - is a range being rendered in model coords
  270.         int first_elem = (int) floor(m_bHorz ? rcV.Left() : rcV.Bottom());
  271.         int last_elem = (int) ceil(m_bHorz ? rcV.Right() : rcV.Top()) -1;
  272.         first_elem = max(m_Start, first_elem);
  273.         last_elem = min(m_End, last_elem);
  274.         if(last_elem >= first_elem) {            
  275.             pane.OpenOrtho(); 
  276.         
  277.             // fill background
  278.             glColorC(m_BackColor);
  279.             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  280.             TModelUnit offset_x = pane.GetOffsetX();    
  281.             glRectd(rcV.Left() - offset_x, rcV.Bottom(), 
  282.                     rcV.Right() - offset_x, rcV.Top());
  283.         
  284.             // render ticks and labels
  285.             x_RenderScale(pane, first_elem, last_elem);
  286.             
  287.             if((m_DisplayOptions & fHideLabels) == 0) {
  288.                 x_RenderAllPosLabels(pane, first_elem, last_elem);  
  289.             }
  290.             pane.Close();
  291.             pane.OpenPixels();
  292.             x_RenderOriginAndMetric(pane);
  293.             pane.Close();
  294.         }
  295.     }
  296. }
  297. int     CRuler::x_ToDisplay(int model) const
  298. {
  299.     return m_Offset + 1 + (m_bReverseDisplay ? (m_End - model) : model);
  300. }
  301. int     CRuler::x_ToModel(int display) const
  302. {
  303.     int off = display - (m_Offset + 1);
  304.     return (m_bReverseDisplay ? (m_End - off) : off);
  305. }
  306. void CRuler::x_RenderScale(CGlPane& pane, int first_elem, int last_elem)
  307. {
  308.     TModelUnit offset_x = pane.GetOffsetX();
  309.     TModelUnit offset_y = pane.GetOffsetY();
  310.     int Length = last_elem - first_elem + 1;
  311.     if(Length > 0)  {                          
  312.         // draw horizonatl line            
  313.         double MinU = m_Start + 0.5;
  314.         double MaxU = m_End + 0.5;
  315.         double u1 = max(MinU, (double) first_elem);
  316.         double u2 = min(MaxU, (double) last_elem + 1);
  317.   
  318.         TModelUnit v1 = 0, v2 = 0, v3 = 0;
  319.         switch(m_LabelPlace)    {
  320.         case eTop:
  321.         case eRight: {
  322.             v1 = m_MajorTickSize;
  323.             v2 = v1 - m_RegTickSize;
  324.             v3 = v1 - m_MajorTickSize;
  325.         }; break;
  326.         case eLeft: {
  327.             v1 = pane.GetVisibleRect().Width() - m_MajorTickSize - 1; 
  328.             v2 = v1 + m_RegTickSize;
  329.             v3 = v1 + m_MajorTickSize;
  330.         };  break;
  331.         case eBottom:   {
  332.             v1 = pane.GetVisibleRect().Height() - m_MajorTickSize - 1; 
  333.             v2 = v1 + m_RegTickSize;
  334.             v3 = v1 + m_MajorTickSize;
  335.         };  break;
  336.         default: _ASSERT(false);
  337.         }
  338.                     
  339.         glColorC(m_RullerColor);
  340.         glBegin(GL_LINES);
  341.     
  342.         if(m_bHorz) {
  343.             glVertex2d(u1 - offset_x, v1 - offset_y);
  344.             glVertex2d(u2 - offset_x, v1 - offset_y);
  345.         } else {
  346.            glVertex2d(v1 - offset_x, u1 - offset_y);
  347.            glVertex2d(v1 - offset_x, u2 - offset_y);
  348.         }
  349.         // draw regular ticks            
  350.         if(m_TickSpace) {   
  351.             int orig_disp = (x_ToDisplay(m_Start) / m_BaseStep) * m_BaseStep;
  352.             int orig = x_ToModel(orig_disp);
  353.             int i_first_disp = (x_ToDisplay(first_elem) / m_TickSpace ) * m_TickSpace;
  354.             int i_last_disp = (x_ToDisplay(last_elem) / m_TickSpace) * m_TickSpace;        
  355.     
  356.             int i_start = x_ToModel(i_first_disp);
  357.             int i_end = x_ToModel(i_last_disp) + m_TickSpace;
  358.             if(i_start < first_elem)
  359.                  i_start += m_TickSpace;
  360.             while(i_end > last_elem)
  361.                 i_end -= m_TickSpace;
  362.             for( int i = i_start; i <= i_end;  i += m_TickSpace ) {
  363.                 double v = ((i - orig) % m_BaseStep) ? v2 : v3;
  364.                 double u = 0.5 + i;
  365.                 if(m_bHorz) {
  366.                     glVertex2d(u - offset_x, v - offset_y);
  367.                     glVertex2d(u - offset_x, v1 - offset_y);
  368.                 } else {
  369.                     glVertex2d(v - offset_x, u - offset_y);
  370.                     glVertex2d(v1 - offset_x, u - offset_y);
  371.                 }
  372.             }
  373.         }        
  374.         glEnd();
  375.     }
  376. }
  377. // This function fills given vector with indeces of the Alignment elements 
  378. // for which position labels should be shown
  379. void  CRuler::x_GenerateLabelPositions(int first_elem, int last_elem, 
  380.                                                vector<int>& vElemPos)
  381. {
  382.     vElemPos.clear();
  383.     const int& step = m_PosLabelsStep;  
  384.     
  385.     // i_start and i_end are positions in model space    
  386.     int i_first_disp = (x_ToDisplay(first_elem) / step ) * step;
  387.     int i_last_disp = (x_ToDisplay(last_elem) / step) * step;        
  388.     
  389.     int i_start = x_ToModel(i_first_disp);
  390.     int i_end = x_ToModel(i_last_disp) + step;
  391.         
  392.     while(i_start < first_elem)
  393.          i_start += step;
  394.     while(i_end > last_elem)
  395.         i_end -= step;
  396.     for( int i = i_start; i <= i_end; i += step )
  397.         vElemPos.push_back(i);
  398. }
  399. /// Renders all labels on the ruller.
  400. void  CRuler::x_RenderAllPosLabels(CGlPane& pane, int first_elem, int last_elem)
  401. {      
  402.     vector<int> vLabelsPos;
  403.     x_GenerateLabelPositions(first_elem, last_elem, vLabelsPos);
  404.     // setup text output params    
  405.     double scale =  m_bHorz ? pane.GetScaleX() : pane.GetScaleY();    
  406.     
  407.     // draw the First Label
  408.     int pos = m_Start;
  409.     string S = x_GetPositionLabel(m_Start);
  410.     
  411.     double label_size = 0;
  412.     if(m_bHorz) {
  413.         label_size = (m_Font.TextWidth(S.c_str()) + kLabelSepPix) * scale;
  414.     } else {
  415.         label_size = (m_Font.TextHeight() + kLabelSepPix) * scale;
  416.     }
  417.     double label_u = 0.5 + m_Start;
  418.     x_RenderPosLabel(pane, label_u, 0, S);
  419.     double low_limit = label_u + label_size;
  420.     // draw the Last label
  421.     label_u = 0.5 + m_End;
  422.     S = x_GetPositionLabel(m_End);    
  423.     
  424.     if(m_bHorz) {
  425.         label_size = m_Font.TextWidth(S.c_str()) * scale;
  426.     }
  427.     if(label_u) // there is enough space at least for the last label
  428.     {
  429.         x_RenderPosLabel(pane, label_u, -label_size, S.c_str()); 
  430.         double high_limit = label_u - (label_size + kLabelSepPix * scale);    
  431.         
  432.         // draw regular labels
  433.         int labels_n = vLabelsPos.size();
  434.         for( int i_label = labels_n - 1; i_label >= 0; i_label-- )  {
  435.             pos = vLabelsPos[i_label];            
  436.             string S = x_GetPositionLabel(pos);
  437.             label_u = pos + 0.5;
  438.             if(m_bHorz) {
  439.                 label_size = m_Font.TextWidth(S.c_str()) * scale;
  440.             }
  441.             double half_size = label_size / 2.0;
  442.             bool b_draw_text = (label_u + half_size < high_limit)  
  443.                                 &&  (label_u - half_size > low_limit);
  444.             if(! b_draw_text)   {
  445.                 S = "";
  446.             } else {
  447.                 high_limit = label_u - half_size;
  448.             }
  449.             x_RenderPosLabel(pane, label_u, -half_size, S);                
  450.         }      
  451.     }
  452. }
  453. /// distnce in pixels between left side of ruler and origin labels
  454. const static int kOriginOffsetX = 6; 
  455. /// minimal size of the metric in pixels
  456. const static int kMinMetricPix = 20;    
  457. /// returns height necessary for drawing ticks and tick labels (if not hidden)
  458. int     CRuler::x_GetBaseHeight() const
  459. {
  460.     int h = m_MajorTickSize + kTextSpaceY;
  461.     if((m_DisplayOptions & fHideLabels) == 0) {
  462.         h +=  m_MajorTickSize + (int)m_Font.TextHeight() + kTextSpaceY;
  463.     }
  464.     return h;
  465. }
  466. void    CRuler::x_RenderOriginAndMetric(CGlPane& pane)
  467. {
  468.     if(m_bHorz) {
  469.         TVPRect rc_vp = pane.GetViewport();
  470.         double t_h = m_Font.GetMetric(CGlBitmapFont::eMetric_FullCharHeight);
  471.         int text_h = (int) ceil(t_h);
  472.         TModelUnit y = rc_vp.Bottom() + x_GetBaseHeight(); // bottoom
  473.         int origin_right = rc_vp.Left(); // rightmost point of the origin label
  474.         if(m_DisplayOptions & fShowOrigin)  {   // render Origin label
  475.             
  476.             int origin = x_ToModel(1) + 1;
  477.             string s = "Origin : " + CTextUtils::FormatSeparatedNumber(origin, true);
  478.             int or_text_w = (int) ceil(m_Font.TextWidth(s.c_str()));
  479.         
  480.             or_text_w = min(or_text_w, rc_vp.Width() - kOriginOffsetX);
  481.             int x = rc_vp.Left() + kOriginOffsetX;
  482.             m_Font.TextOut(x, y, or_text_w, text_h, s.c_str()); // render label
  483.             origin_right += kOriginOffsetX + or_text_w;
  484.         }
  485.         if(m_DisplayOptions & fShowMetric)  {
  486.             // choose metric size
  487.             TModelUnit scale_x = pane.GetScaleX();
  488.             TModelUnit step = m_BaseStep;        
  489.             while(step / scale_x < kMinMetricPix)  {
  490.                 step *= 10;
  491.             }
  492.             int pix_l = (int) ceil(step / scale_x); //length of metric in pixels
  493.             string s = CTextUtils::FormatSeparatedNumber((int) step, true);       
  494.             s += "  ";
  495.             int text_w = (int) ceil(m_Font.TextWidth(s.c_str()));
  496.         
  497.             int metric_w = max(pix_l, text_w);        
  498.             if(origin_right + metric_w + kOriginOffsetX < rc_vp.Right()) { 
  499.                 // there is enough space for rendering metric
  500.                 TModelUnit x = rc_vp.Right() - kOriginOffsetX - metric_w;        
  501.                 TModelUnit yc = y + max(text_h, m_MajorTickSize) / 2;
  502.                 
  503.                 TModelUnit y1 = yc + m_MajorTickSize / 2;                
  504.                 TModelUnit y2 = yc - m_MajorTickSize / 2;                
  505.                 glBegin(GL_LINES);
  506.                     glVertex2d(x, y1);
  507.                     glVertex2d(x, y2);
  508.                     
  509.                     glVertex2d(x, yc);
  510.                     glVertex2d(x + pix_l, yc);
  511.                     
  512.                     glVertex2d(x + pix_l, y1);
  513.                     glVertex2d(x + pix_l, y2);            
  514.                 glEnd();                
  515.                 m_Font.TextOut(x - text_w, y, text_w, text_h, s.c_str(), FL_ALIGN_RIGHT);                
  516.             }
  517.         }
  518.     }
  519. }
  520. // pos_u is in model coords
  521. void  CRuler::x_RenderPosLabel(CGlPane& pane, double pos_u, 
  522.                                 double u_label_offset, const string& s_text )
  523. {
  524.     TModelUnit offset_x = pane.GetOffsetX();
  525.     TModelUnit offset_y = pane.GetOffsetY();
  526.     
  527.     if(m_bHorz) { // horizontal orientation
  528.         TModelUnit y1, y2, text_y;
  529.         TModelUnit tick_h = 2 * m_MajorTickSize;
  530.     
  531.         if(m_LabelPlace == eTop)    {
  532.             y1 = 0; 
  533.             y2 = tick_h;
  534.             text_y = y2 + kTextSpaceY;
  535.         } else {
  536.             y2 = pane.GetVisibleRect().Top();
  537.             y1 = y2 - tick_h;
  538.             text_y = y1 - kTextSpaceY - m_Font.TextHeight();
  539.         }
  540.         glColorC(m_TextColor);
  541.         m_Font.TextOut(pos_u + u_label_offset - offset_x, text_y - offset_y, s_text.c_str());  
  542.         
  543.         // draw label's tick
  544.         glColorC(m_RullerColor);
  545.         glBegin(GL_LINES);
  546.             glVertex2d(pos_u - offset_x, y1 - offset_y);
  547.             glVertex2d(pos_u - offset_x, y2 - offset_y);
  548.         glEnd();
  549.     } else { // vertical orientation
  550.         TModelUnit tick_w = 2 * m_MajorTickSize;
  551.         TModelUnit text_w = pane.GetVisibleRect().Width() - tick_w;
  552.         
  553.         TModelUnit y = pos_u + u_label_offset;
  554.         TModelUnit h = m_Font.TextHeight();
  555.         
  556.         TModelUnit x0 = pane.GetVisibleRect().Left();
  557.         TModelUnit tick_x = text_w;
  558.         if (m_LabelPlace == eRight)  {
  559.             x0 += tick_w + kLabelSepX;
  560.             tick_x = 0;
  561.         }
  562.         int text_align = FL_ALIGN_BOTTOM | ((m_LabelPlace == eRight) 
  563.                                     ? FL_ALIGN_LEFT : FL_ALIGN_RIGHT);
  564.         
  565.         glColorC(m_TextColor);
  566.         m_Font.TextOut(x0 - offset_x, y - offset_y, text_w - kLabelSepX, h, s_text.c_str(), text_align);  
  567.         // draw label's tick
  568.         glColorC(m_RullerColor);
  569.         glBegin(GL_LINES);
  570.             glVertex2d(tick_x - offset_x, pos_u - offset_y);
  571.             glVertex2d(tick_x + tick_w - offset_x, pos_u - offset_y);            
  572.         glEnd();
  573.     }
  574. }
  575. // i_elem is in model coords
  576. string  CRuler::x_GetPositionLabel(int i_elem)
  577. {
  578.     int pos = x_ToDisplay(i_elem);
  579.     string S = CTextUtils::FormatSeparatedNumber(pos, true);
  580.     return S;
  581. }
  582. END_NCBI_SCOPE
  583. /*
  584.  * ===========================================================================
  585.  * $Log: ruler.cpp,v $
  586.  * Revision 1000.4  2004/06/01 21:10:43  gouriano
  587.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
  588.  *
  589.  * Revision 1.15  2004/05/21 22:27:54  gorelenk
  590.  * Added PCH ncbi_pch.hpp
  591.  *
  592.  * Revision 1.14  2004/03/23 14:07:37  dicuccio
  593.  * Fixed compiler warnings
  594.  *
  595.  * Revision 1.13  2004/03/04 19:31:48  yazhuk
  596.  * Improved layout, labels spacing
  597.  *
  598.  * Revision 1.12  2004/03/02 21:54:12  yazhuk
  599.  * Added rendering of origin and metric
  600.  *
  601.  * Revision 1.11  2004/02/17 15:23:10  yazhuk
  602.  * Refactoring - replaced CGlParam with CGlAttrGuard
  603.  *
  604.  * Revision 1.10  2004/02/11 15:24:57  yazhuk
  605.  * Fixed background rendering
  606.  *
  607.  * Revision 1.9  2003/12/23 17:39:19  yazhuk
  608.  * Fixed bug with labels generation in "reverse" mode.
  609.  *
  610.  * Revision 1.8  2003/12/12 17:37:24  ivanov
  611.  * Explicit using pow(double,double) to avoid compilation error on MSVC 7
  612.  *
  613.  * Revision 1.7  2003/12/10 16:55:34  yazhuk
  614.  * Implemented control over displayed range, offset and direction.
  615.  *
  616.  * Revision 1.6  2003/12/08 15:12:02  yazhuk
  617.  * Fixed "first label is always 1" problem. Workaround for OpenGL
  618.  * rounding/precision problems.
  619.  *
  620.  * Revision 1.5  2003/12/01 16:36:06  yazhuk
  621.  * Improved labels layout algorithm and ruller ticks rendering .
  622.  *
  623.  * Revision 1.4  2003/11/18 17:57:08  yazhuk
  624.  * Fixed GCC warnings
  625.  *
  626.  * Revision 1.3  2003/11/18 00:59:03  yazhuk
  627.  * Restored IRenderable implementation
  628.  *
  629.  * Revision 1.2  2003/11/17 23:43:12  yazhuk
  630.  * Fixed GCC compilation problem.
  631.  *
  632.  * Revision 1.1  2003/11/17 20:24:19  yazhuk
  633.  * Renamed from ruller.cpp
  634.  *
  635.  * Revision 1.2  2003/10/31 14:04:18  dicuccio
  636.  * Corrected spelling error: CRuller -> CRuler
  637.  *
  638.  * Revision 1.1  2003/10/29 23:18:28  yazhuk
  639.  * Initial revision
  640.  *
  641.  * ===========================================================================
  642.  */