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 + -
显示快捷键?