ruler.cpp

来自「ncbi源码」· C++ 代码 · 共 722 行 · 第 1/2 页

CPP
722
字号
/* * =========================================================================== * PRODUCTION $Log: ruler.cpp,v $ * PRODUCTION Revision 1000.4  2004/06/01 21:10:43  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15 * PRODUCTION * =========================================================================== *//*  $Id: ruler.cpp,v 1000.4 2004/06/01 21:10:43 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors:  Andrey Yazhuk * * File Description: * */#include <ncbi_pch.hpp>#include <corelib/ncbistd.hpp>#include <gui/opengl/glhelpers.hpp>#include <gui/widgets/gl/ruler.hpp>#include <math.h>BEGIN_NCBI_SCOPECRuler::CRuler(bool b_horz):   m_bHorz(b_horz),    m_bAutoRange(true),    m_Start(0),    m_End(0),    m_Offset(0),    m_bReverseDisplay(false),    m_DisplayOptions(0),    m_Font(CGlBitmapFont::eHelvetica12),    m_TextColor(0.2f, 0.4f, 0.2f),    m_RullerColor(0.2f, 0.2f, 0.2f),    m_BackColor(0.95f, 0.95f, 0.95f),    m_MajorTickSize(6),    m_RegTickSize(3),    m_bDirty(true),    m_PosLabelsStep(-1){    m_LabelPlace = m_bHorz ? eBottom : eLeft;}CRuler::~CRuler(){}void    CRuler::SetHorizontal(bool b_horz, ELabelPlacement place){    m_bHorz = b_horz;    if(m_bHorz) {        switch(place)   {        case eLeft:        case eRight:    _ASSERT(false);        case eDefault:         case eBottom: m_LabelPlace = eBottom; break;        case eTop: m_LabelPlace = eTop; break;        }    } else {        switch(place)   {        case eBottom:        case eTop:    _ASSERT(false);        case eDefault:         case eLeft: m_LabelPlace = eLeft; break;        case eRight: m_LabelPlace = eRight; break;        }    }    m_bDirty = true;}void    CRuler::SetColor(EColorType type, const CGlColor& color){    switch(type)    {    case eRuller: m_RullerColor = color; break;    case eText: m_TextColor = color; break;    case eBackground: m_BackColor = color; break;    default: _ASSERT(false);    }    m_bDirty = true;}void    CRuler::SetFont(CGlBitmapFont::EFont font_type){    m_Font.SetFont(font_type);    m_bDirty = true;}void    CRuler::SetDisplayOptions(int options){    m_DisplayOptions = options;}void    CRuler::SetAutoRange(){    m_bAutoRange = true;    m_Offset = 0;    m_bReverseDisplay = false;}void    CRuler::SetRange(int Start, int End, int SeqStart, bool b_reverse){    m_bAutoRange = false;    m_Start = Start;    m_End = End;    m_Offset = SeqStart - (b_reverse ? 0 : m_Start);    m_bReverseDisplay = b_reverse;}void    CRuler::SetGeometryParam(EGeometryParam geom, int value){    switch(geom)    {    case eRegularTickHeight: m_RegTickSize = value;    break;    case eMajorTickHeight: m_MajorTickSize = value;    break;    default: _ASSERT(false);    }    m_bDirty = true;}/// vertical spacing between text and borders or between text and other graphicsstatic int  kTextSpaceY = 3; TVPPoint     CRuler::GetPreferredSize() const{    int w = 0, h = 0;    if(m_bHorz) {        h = x_GetBaseHeight();        if(m_DisplayOptions & (fShowOrigin | fShowMetric))  {            double t_h = m_Font.GetMetric(CGlBitmapFont::eMetric_FullCharHeight);            int text_h = (int) ceil(t_h);            h += max(text_h, m_MajorTickSize) + kTextSpaceY;        }    } else {            }    return TVPPoint(w, h);}TVPRect    CRuler::GetVPRect(){    TVPPoint pt = GetPreferredSize();    return TVPRect(0, 0, pt.X(), pt.Y());}TModelRect CRuler::GetModelRect(){    return TModelRect();}const static int kLabelSepX = 8;const static int kLabelSepY = 4;const static int kMinTickStepPixels = 5;const static int kLabelSepPix = 24; // min distance between labels// calculates distance in pixels between position labelsvoid CRuler::x_CalculatePosLabelsStep(CGlPane& pane){    m_MaxLabelH = m_Font.TextHeight();    double char_w = m_Font.GetMetric(CGlBitmapFont::eMetric_AvgCharWidth);                double comma_w = m_Font.TextWidth(",");        // determining maximal number of characters in a label    double max_num = max(x_ToDisplay(m_Start), x_ToDisplay(m_End));         int digits_count = (int) ceil(log10(max_num));        int commas_count = (digits_count - 1) / 3;        // length of the longest possible label in pixels (add 2 for separation)    m_MaxLabelW = kLabelSepPix + digits_count * char_w + commas_count * comma_w;     // calculate size of the longest label in model coords    double scale = m_bHorz ? pane.GetScaleX() : pane.GetScaleY();    double max_label_sym = 0;  // in symbols    if(m_bHorz) {                max_label_sym = scale * m_MaxLabelW;            } else {        max_label_sym = 2 * scale * m_MaxLabelH;    }        // choosing step in model coords    double log = (max_label_sym >= 1.0) ? log10(max_label_sym) : 0;    log = ceil(log);    double step = pow((double)10, log);    double base_step = step;    if(step > 10.001)   {        // try to mimimize step without intersecting labels        if(m_bHorz)   {            // using compact notation (1 K vs 1,000) saves space, check if we can             // benefit from this            // adjusting order            int groups_n = 0;            step = step * 10; // to compensate effect of fisrt iteration            double max_label_w = m_MaxLabelW;            do            {                _ASSERT(step > 0);                step = step / 10;                log = ceil(log10(step));                groups_n = (int) (log / 3);                if(groups_n)  {                    int d_digits =  3 * groups_n - 2;                     max_label_w = m_MaxLabelW - d_digits * char_w + groups_n * comma_w;                    max_label_sym = scale * max_label_w;                }            } while(groups_n  &&  step > max_label_sym * 10);            m_MaxLabelW = max_label_w;            base_step = step;        }        // currently step has a form   10^X, lets check if we can choose        // a smaller step in a form  K * 10^(X-1), where K = 2, 5        // this adjusment does not affect labels size        if(step > max_label_sym * 5)    {            base_step = step / 10;  // 10^(X-1)            step = step / 5;        // 2 * 10^(X-1)        }        else if(step > max_label_sym * 2)   {            base_step = step / 10;  // 10^(X-1)            step = step / 2;        // 5 * 10^(X-1)                  }    }            m_BaseStep = (int) base_step;    m_BaseStep = max(m_BaseStep, 1);    m_PosLabelsStep = (int) step;    m_PosLabelsStep  = max(m_PosLabelsStep , 1);    // choosing optimal distance between ticks    m_TickSpace = m_BaseStep;    int ar_K[] = { 10, 5 ,2 };    for( int i = 0; i < 3; i++ )    {        int space = m_TickSpace / ar_K[i];        if(space >= 1  &&  space / scale > kMinTickStepPixels)   {            m_TickSpace = space;             break;        }    }    m_bDirty = false;}void  CRuler::Render(CGlPane& pane){    CGlAttrGuard AttrGuard(GL_POLYGON_BIT | GL_LINE_BIT);    glLineWidth(1.0f);    const TModelRect& rc_lim = pane.GetModelLimitsRect();            if(m_bAutoRange)    {        m_Start = (int) (m_bHorz ? rc_lim.Left() : rc_lim.Bottom());        m_End = (int) (m_bHorz ? rc_lim.Right() : rc_lim.Top()) - 1;    }    bool b_update = m_bDirty || m_PosLabelsStep <= 0;    if(! b_update)  {        bool b_scale_changed = m_bHorz ? (m_ScaleX != pane.GetScaleX())                                       : (m_ScaleY != pane.GetScaleY());        b_update =  b_scale_changed  ||  ! (m_rcLimits == rc_lim);                m_rcLimits = rc_lim;        m_ScaleX = pane.GetScaleX();        m_ScaleY = pane.GetScaleY();    }    if(b_update)           x_CalculatePosLabelsStep(pane);        if(m_PosLabelsStep > 0) { // step is valid        // calculating range to draw        TModelRect rcV = pane.GetVisibleRect();                // [first_elem, last_elem] - is a range being rendered in model coords        int first_elem = (int) floor(m_bHorz ? rcV.Left() : rcV.Bottom());        int last_elem = (int) ceil(m_bHorz ? rcV.Right() : rcV.Top()) -1;        first_elem = max(m_Start, first_elem);        last_elem = min(m_End, last_elem);        if(last_elem >= first_elem) {                        pane.OpenOrtho();                     // fill background            glColorC(m_BackColor);            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);            TModelUnit offset_x = pane.GetOffsetX();                glRectd(rcV.Left() - offset_x, rcV.Bottom(),                     rcV.Right() - offset_x, rcV.Top());                    // render ticks and labels            x_RenderScale(pane, first_elem, last_elem);                        if((m_DisplayOptions & fHideLabels) == 0) {                x_RenderAllPosLabels(pane, first_elem, last_elem);              }            pane.Close();            pane.OpenPixels();            x_RenderOriginAndMetric(pane);            pane.Close();        }    }}int     CRuler::x_ToDisplay(int model) const{    return m_Offset + 1 + (m_bReverseDisplay ? (m_End - model) : model);}int     CRuler::x_ToModel(int display) const{    int off = display - (m_Offset + 1);    return (m_bReverseDisplay ? (m_End - off) : off);}void CRuler::x_RenderScale(CGlPane& pane, int first_elem, int last_elem){    TModelUnit offset_x = pane.GetOffsetX();    TModelUnit offset_y = pane.GetOffsetY();    int Length = last_elem - first_elem + 1;    if(Length > 0)  {                                  // draw horizonatl line                    double MinU = m_Start + 0.5;        double MaxU = m_End + 0.5;        double u1 = max(MinU, (double) first_elem);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?