align_row.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:34k
- /*
- * ===========================================================================
- * PRODUCTION $Log: align_row.cpp,v $
- * PRODUCTION Revision 1000.5 2004/06/01 21:07:00 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.41
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: align_row.cpp,v 1000.5 2004/06/01 21:07:00 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 <corelib/ncbitime.hpp>
- #include <math.h>
- #include <gui/types.hpp>
- #include <gui/opengl/glhelpers.hpp>
- #include <gui/opengl/glbitmapfont.hpp>
- #include <objmgr/graph_ci.hpp>
- #include <objects/general/Dbtag.hpp>
- #include <objects/general/Object_id.hpp>
- #include <gui/widgets/aln_multiple/align_row.hpp>
- #include <gui/widgets/aln_multiple/aln_scoring.hpp>
- #include <gui/widgets/aln_multiple/trace_graph.hpp>
- #include <objmgr/util/sequence.hpp>
- #include <FL/Fl.H>
- BEGIN_NCBI_SCOPE
- USING_SCOPE(ncbi::objects);
- ////////////////////////////////////////////////////////////////////////////////
- ///
- const CGlColor& CAlnVecRowDisplayStyle::GetAlignTextColor() const
- {
- return m_AlignTextColor;
- }
- const CGlColor& CAlnVecRowDisplayStyle::GetAlignColor() const
- {
- return m_AlignColor;
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// CAlnVecRow
- CAlnVecRow::CAlnVecRow(const CAlnVecRowHandle& handle)
- : m_Handle(handle),
- m_pHost(NULL),
- m_BaseHeight(0),
- m_bExpanded(false),
- m_pStyle(NULL),
- m_pCache(NULL),
- m_pGraph(NULL),
- m_PixLeft(-1), m_PixRight(-1), m_ModelLeft(-1), m_ModelRight(-1)
- {
- const CSeq_id& id = sequence::GetId(m_Handle.GetBioseqHandle(),
- sequence::eGetId_Best);
- id.GetLabel(&m_Text);
- /// instantiate but do not create
- m_pGraph = new CTraceGraph(handle.GetBioseqHandle(), handle.IsNegativeStrand());
- m_bExpanded = false;
- }
- CAlnVecRow::~CAlnVecRow()
- {
- delete m_pGraph;
- m_DList.Delete();
- m_pStyle = NULL; //do not delete
- }
- void CAlnVecRow::x_CreateGraph()
- {
- m_pGraph->Create();
- }
- void CAlnVecRow::x_DestroyGraph()
- {
- m_pGraph->Destroy();
- }
- void CAlnVecRow::SetScoreCache(CScoreCache* cache)
- {
- m_pCache = cache;
- }
- void CAlnVecRow::GraphicsCacheCmd(EGraphCacheCmd cmd)
- {
- switch(cmd) {
- case eInvalidate: m_DList.Invalidate(); break;
- case eDelete: m_DList.Delete(); break;
- }
- }
- void CAlnVecRow::GetHTMLActiveAreas(EColumnType col_type, CGlPane& pane, TAreaVector& areas)
- {
- switch(col_type) {
- case eIcons: {
- string s_row = NStr::IntToString(m_Handle.GetRowNum());
- CHTMLActiveArea area(CHTMLActiveArea::eCheckBox,
- x_GetButtonRect(pane, eExpand),
- s_row, "Click to expand/collapse", "toggle_expand");
- areas.push_back(area);
- }; break;
- case eAlignment: {
- // create area for alignment
- TSignedSeqPos start = m_Handle.GetSeqAlnStart();
- TSignedSeqPos stop = m_Handle.GetSeqAlnStop();
- const TModelRect& rc_vis = pane.GetVisibleRect();
- start = max(start, (TSignedSeqPos) floor(rc_vis.Left()) );
- stop = min(stop, (TSignedSeqPos) ceil(rc_vis.Right()) );
-
- pane.OpenOrtho();
- pane.Close();
- TVPUnit vp_start = pane.ProjectX(start);
- TVPUnit vp_stop = pane.ProjectX(stop);
- TVPRect rc = pane.GetViewport();
- rc.SetHorz(vp_start, vp_stop);
-
- string s_row = NStr::IntToString(m_Handle.GetRowNum());
- CHTMLActiveArea area(CHTMLActiveArea::eLink, rc,
- s_row, m_Text, "");
- areas.push_back(area);
- }; break;
- default: break;
- };
- }
- /// height of "white-space" between row borders and alignment band
- static const int kAlignSpace = 2;
- /// height of sub-bands where the colored according to the exreme score values (min or max)
- static const int kExtremeArea = 3;
- static const int kGapExtremeArea = 1;
- /// vertical offset from the border of the alignment band to the border of gap band
- static const int kGapOffset = 4;
- static const int kTextVertSpace = 1;
- static const int kSeqVertSpace = kAlignSpace + 2;
- void CAlnVecRow::SetDisplayStyle(const CRowDisplayStyle* style)
- {
- m_pStyle = dynamic_cast<const CAlnVecRowDisplayStyle*>(style);
- float h1 = kTextVertSpace * 2;
- float h2 = kSeqVertSpace * 2;
- if(m_pStyle)
- {
- h1 += m_pStyle->GetTextFont().TextHeight();
- h2 += m_pStyle->GetSeqFont().TextHeight();
- }
- m_Height = m_BaseHeight = (int) max(h1, h2);
- if(m_bExpanded) {
- if(m_pGraph) {
- m_Height += m_pGraph->GetPreferredHeight();
- }
- }
- }
- const CRowDisplayStyle* CAlnVecRow::GetDisplayStyle()
- {
- return m_pStyle;
- }
- void CAlnVecRow::SetHost(IAlignRowHost* pHost)
- {
- m_pHost = pHost;
- }
- int CAlnVecRow::GetRowNum() const
- {
- return m_Handle.GetRowNum();
- }
- int CAlnVecRow::GetHeightPixels() const
- {
- return m_Height;
- }
- void CAlnVecRow::RenderColumn(EColumnType col_type, CGlPane& pane, int State)
- {
- CGlAttrGuard AttrGuard(GL_POLYGON_MODE);
- if(m_pStyle) {
- switch(col_type) {
- case eDescr: x_RenderDescr(pane, State); break;
- case eIcons: x_RenderIcons(pane); break;
- case eStart: x_RenderStartPos(pane); break;
- case eAlignment: x_RenderAlign(pane); break;
- case eEnd: x_RenderEndPos(pane); break;
- case eSeqEnd: x_RenderSeqEnd(pane); break;
- default: break; // unknown column
- }
- }
- }
- int CAlnVecRow::handle(CGUIEvent& event, EColumnType col_type, CGlPane& pane)
- {
- switch(event.GetFLTKEvent()) {
- case FL_PUSH: {
- if(Fl::event_button() == FL_LEFT_MOUSE) {
- TVPPoint pt = x_GetHost()->ARH_GetVPMousePos();
- TVPRect rc_btn = x_GetButtonRect(pane, eExpand);
- if(rc_btn.PtInRect(pt)) {
- x_OnClickExpandBtn();
- return 1;
- }
- }
- }; break;
- default: break;
- }
- return 0;
- }
- static const int kTooltipMaxLines = 5;
- static const int kMaxSeqInTooltip = 20;
- string CAlnVecRow::GetTooltip(EColumnType col_type, CGlPane& pane)
- {
- switch(col_type) {
- case eIcons: return x_GetIconsTooltip(pane);
- case eStart: return "First visible position in sequence coordinates";
- case eAlignment: return x_GetAlignmentTooltip(pane);
- case eEnd: return "Last visible position in sequence coordinates";
- case eSeqEnd: return "Last position in sequence";
- default: break;
- }
- return "";
- }
- string CAlnVecRow::x_GetIconsTooltip(CGlPane& pane)
- {
- _ASSERT(x_GetHost());
- string s_tip;
- TVPPoint pt = x_GetHost()->ARH_GetVPMousePos();
- TVPRect rc_btn = x_GetButtonRect(pane, eExpand);
- if(rc_btn.PtInRect(pt)) {
- if(IsExpandable()) {
- s_tip = "Click to ";
- s_tip += m_bExpanded ? "collapse" : "expand";
- } else {
- s_tip = "Nothing to expand";
- }
- } else {
- rc_btn = x_GetButtonRect(pane, eSetupGraphs);
- if(rc_btn.PtInRect(pt)) {
- s_tip = "Setup Graphs";
- }
- }
- return s_tip;
- }
- #define TOOLTIP_RANGE_PIX 3
- inline void glLined(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2)
- {
- glVertex2d(x1, y1);
- glVertex2d(x2, y2);
- }
- string FormatRange(TSignedSeqPos from, TSignedSeqPos to)
- {
- string s = NStr::IntToString(to + 1);
- s += "-";
- s += NStr::IntToString(to + 1);
- return s;
- }
- string CAlnVecRow::x_GetAlignmentTooltip(CGlPane& pane)
- {
- pane.OpenOrtho();
- pane.Close();
- double w_x = pane.UnProjectX(Fl::event_x());
- double pix_w = pane.UnProjectWidth(TOOLTIP_RANGE_PIX);
- // append Name and Position
- string s_tip = m_Text;
- if(m_Handle.IsNegativeStrand())
- s_tip += ", Negative Strand";
- TSeqPos pos = (TSeqPos) w_x;
- s_tip += string("nPos ") + NStr::IntToString(pos + 1);
- TSignedSeqPos seq_pos = m_Handle.GetSeqPosFromAlnPos(pos);
- if(seq_pos >= 0) {
- s_tip += ", on Sequence ";
- s_tip += NStr::IntToString(seq_pos + 1);
- }
- // Append information on gaps and inserts
- TSeqPos start = (TSeqPos) floor(w_x - pix_w / 2);
- TSeqPos end = (TSeqPos) ceil(w_x + pix_w / 2);
- CAlnMap::TSignedRange range(start, end);
- // obtain chunks in the range [start, end]
- CRef<CAlnVec::CAlnChunkVec> v_chunks = m_Handle.GetAlnChunks(range,
- CAlnVec::fAllChunks | CAlnVec::fDoNotTruncateSegs);
- int chunks_n = min((int) v_chunks->size(), kTooltipMaxLines);
- if(chunks_n) { // show chunks tooltip
- string seq;
- for (int i = 0; i < chunks_n; i++) {
- CConstRef<CAlnMap::CAlnChunk> chunk = (*v_chunks)[i];
- CAlnMap::TSegTypeFlags type = chunk->GetType();
- const TSignedSeqRange& aln_r = chunk->GetAlnRange();
- const TSignedSeqRange& seq_r = chunk->GetRange();
- if((type & CAlnMap::fSeq) && (type & CAlnMap::fNotAlignedToSeqOnAnchor)) { //insert
- //generate string for sequence
- TSeqRange seq_r(chunk->GetRange().GetFrom(), chunk->GetRange().GetTo());
- bool b_ellipsis = false;
- if((int) seq_r.GetLength() > kMaxSeqInTooltip) { // to long to be displayed
- seq_r.SetToOpen(seq_r.GetFrom() + kMaxSeqInTooltip);
- b_ellipsis = true;
- }
- m_Handle.GetSeqString(seq, seq_r);
- if(b_ellipsis)
- seq += "...";
- // generate a string for the chunk
- TSeqPos aln_left = aln_r.GetToOpen(); // a bit of hack
- s_tip += "nInsert ";
- s_tip += FormatRange(aln_left, aln_left + 1);
- s_tip += ", on Sequence ";
- s_tip += FormatRange(seq_r.GetFrom(), seq_r.GetTo() + 1);
- s_tip += " : ";
- s_tip += seq;
- } else if(type == 0) {
- // generate string for gap
- s_tip += "nGap ";
- s_tip += FormatRange(aln_r.GetFrom() + 1, aln_r.GetTo() + 1);
- s_tip += ", on Sequence ";
- s_tip += FormatRange(seq_r.GetFrom() + 1, seq_r.GetTo() + 1);
- }
- }
- }
- return s_tip;
- }
- void CAlnVecRow::x_OnClickExpandBtn()
- {
- fl_cursor(FL_CURSOR_WAIT);
- Expand(! IsExpanded());
- fl_cursor(FL_CURSOR_DEFAULT);
- }
- /// Renders graphical part of the row
- void CAlnVecRow::x_RenderAlign(CGlPane& pane)
- {
- _ASSERT(m_pStyle);
- pane.OpenOrtho();
- TModelUnit offset_x = pane.GetOffsetX();
- TModelUnit offset_y = pane.GetOffsetY();
- TModelRect rc_lim = pane.GetModelLimitsRect();
- TModelRect rc_model = pane.GetVisibleRect();
- TModelUnit y2 = rc_lim.Top() + kAlignSpace - offset_y;
- TModelUnit y1 = rc_lim.Top() + m_BaseHeight -1 - kAlignSpace - offset_y;
- TSeqPos row_start = m_Handle.GetSeqAlnStart();
- TSeqPos row_stop = m_Handle.GetSeqAlnStop();
- glLineWidth(1.0f);
- glColorC(m_pStyle->GetAlignColor());
- // now render segments actually present
- unsigned Left = (unsigned) floor(rc_model.Left());
- unsigned Right = (unsigned) ceil(rc_model.Right());
- CAlnMap::TSignedRange Range(Left, Right);
- // render aligned segments
- CRef<CAlnVec::CAlnChunkVec> vAlnChunks = m_Handle.GetAlnChunks(Range, CAlnVec::fSkipInserts);
- if(m_pCache) { // render parts of chunks accordingly to scores
- pane.Close();
- x_RenderAlignScores(pane, vAlnChunks);
- pane.OpenOrtho();
- } else { // scores are not available - render all chunks with a default color
- // render a single line for all possible gaps
- TModelUnit Yc = (y2 + y1) / 2;
- glBegin(GL_LINES);
- glLined(row_start - offset_x, Yc, row_stop - offset_x, Yc);
- glEnd();
- x_RenderAlignSegments(pane, vAlnChunks, (int) y1, (int) y2);
- }
- // render inserts
- CRef<CAlnVec::CAlnChunkVec> vChunks = m_Handle.GetAlnChunks(Range, CAlnVec::fInsertsOnly);
- glColor3d(0, 0, 0.5);
- glBegin(GL_LINES);
- for (int i = 0; i < vChunks->size(); i++) {
- CConstRef<CAlnMap::CAlnChunk> chunk = (*vChunks)[i];
- _ASSERT(chunk->GetType() & CAlnMap::fSeq);
- _ASSERT(chunk->GetType() & CAlnMap::fNotAlignedToSeqOnAnchor);
- TModelUnit ins_pos = chunk->GetAlnRange().GetFrom() - offset_x;
- TModelUnit len = chunk->GetRange().GetLength();
- TModelUnit x1 = ins_pos - len / 2;
- TModelUnit x2 = x1 + len;
- // assuming glBegin(GL_LINES)
- glLined(ins_pos, y1, ins_pos, y2);
- glLined(x1, y1, x2, y1);
- glLined(x1, y2, x2, y2);
- }
- glEnd();
- // render sequence if its visible
- if(x_CanRenderSeq(pane))
- {
- double H = m_pStyle->GetSeqFont().TextHeight();
- double y = floor((y1 + y2 + H) / 2);
- x_RenderSequence(pane, y, Left, Right);
- }
- pane.Close();
- x_RenderGraph(pane, vAlnChunks);
- }
- void CAlnVecRow::x_RenderAlignSegments(CGlPane& pane, TRefChunks& chunks, int top_y, int bottom_y)
- {
- glColorC(m_pStyle->GetAlignColor());
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- TModelUnit offset_x = pane.GetOffsetX();
- for (int i = 0; i < chunks->size(); i++) {
- CConstRef<CAlnMap::CAlnChunk> chunk = (*chunks)[i];
- if((chunk->GetType() & CAlnMap::fSeq)) {
- _ASSERT((chunk->GetType() & CAlnMap::fNotAlignedToSeqOnAnchor) == 0);
- const TSignedSeqRange& R = chunk->GetAlnRange();
- glRectd(R.GetFrom() - offset_x, top_y,
- R.GetToOpen() - offset_x, bottom_y);
- }
- }
- }
- /// Renders alignment (graphical) part of the row according to scores.
- /// Score intervals are rendered differently depending on their size.
- /// Long intervals ("long" meaning covering more than one full pixel) are rendered in
- /// "vector" mode - the series of pixels corresponding to a single interval
- /// is drawn as a single rectangle with color defined by the intreval's score.
- /// Short intervals are rendered in "raster" mode - algorithm iterates by intervals
- /// and calculates average and maximal scores corresponding to a particular pixel,
- /// then each pixel is drawn with its individual color.
- void CAlnVecRow::x_RenderAlignScores(CGlPane& pane, TRefChunks& chunks)
- {
- pane.OpenPixels();
- const TVPRect& rc_vp = pane.GetViewport();
- const TModelRect rc_vis = pane.GetVisibleRect();
- glTranslated(0.0, rc_vp.Top(), 0.0); // to make the display list "scrollable" vertically
- // if horz projection has changed - invalidate display list
- if(m_PixLeft != rc_vp.Left() || m_PixRight != rc_vp.Right()
- || m_ModelLeft != rc_vis.Left() || m_ModelRight != rc_vis.Right()) {
- m_DList.Invalidate();
- m_PixLeft = rc_vp.Left();
- m_PixRight = rc_vp.Right();
- m_ModelLeft = rc_vis.Left();
- m_ModelRight = rc_vis.Right();
- }
- if(m_DList.IsValid()) {
- m_DList.Call();
- } else { // need to create a new one
- m_DList.Begin(GL_COMPILE_AND_EXECUTE);
- TModelUnit left = rc_vis.Left();
- TModelUnit scale_x = pane.GetScaleX();
- int range_pix_start = rc_vp.Left();
- int range_pix_end = rc_vp.Right();
- // visible alignment range in seq coords
- int range_from = (int) (floor(left));
- // int range_to_open = (int) (ceil(pane.GetVisibleRect().Right()));
- int top_y = - kAlignSpace;
- int bottom_y = - m_BaseHeight + kAlignSpace;
- int off_y = 0, extr_off_y = 0;
- // obtain Score Collection and setup iterators
- const CScoreCache::TScoreColl& ScoreColl = m_pCache->GetScores(m_Handle.GetRowNum());
- CScoreCache::TScoreColl::const_iterator it = ScoreColl.begin();
- const CScoreCache::TScoreColl::const_iterator it_end = ScoreColl.end();
- it = ScoreColl.find(it, it_end, range_from);
- double int_score;
- double pix_start, pix_end;
- double score_sum = 0, score_min = 0, score_len = 0;
- bool b_first = true; // "true" if pixel is being processed for the first time
- bool b_new_interval = true;
- bool b_lines = true;
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glBegin(GL_LINES);
- int i_prev_chunk = -1, i_chunk = 0, n_chunks = chunks->size();
- CConstRef<CAlnMap::CAlnChunk> chunk;
- // [pos_start, pos_end) defines range being processed
- int pos_start = -1, pos_end = range_from;
- bool b_skip = false;
- // iterate by pixels, score intervals and chunks
- for( int pix = range_pix_start;
- pix <= range_pix_end && it != it_end && i_chunk < n_chunks; )
- {
- if(i_prev_chunk != i_chunk) {
- chunk = (*chunks)[i_chunk];
- int type = chunk->GetType();
- b_skip = false;
- if(type & CAlnMap::fSeq) { // aligned segment
- off_y = 0;
- extr_off_y = kExtremeArea;
- } else if(type & (CAlnVec::fNoSeqOnRight | CAlnVec::fNoSeqOnLeft)) {
- // empty space - do not draw anything
- b_skip = true;
- } else { // gap
- off_y = kGapOffset ;
- extr_off_y = kGapOffset + kGapExtremeArea;
- }
- }
- if(b_new_interval) { // new range
- int_score = it->GetAttr();
- }
- if(i_chunk != i_prev_chunk || b_new_interval) {
- // [pos_start, pos_end) is defined as intersection of current score interval
- // and current chunk
- pos_start = pos_end;
- pos_end = min((int) chunk->GetAlnRange().GetToOpen(), (int) it->GetToOpen());
- // transform from seq. coords to pixels
- pix_start = range_pix_start + ((double) (pos_start - left)) / scale_x;
- pix_end = range_pix_start + ((double) (pos_end - left)) / scale_x;
- i_prev_chunk = i_chunk;
- b_new_interval = false;
- }
- if(b_skip && (pix_start <= pix && pix_end >= pix + 1)) {
- int strip_end = (int) ceil(pix_end) - 1;
- if(! b_skip) {
- if(b_lines) {
- glEnd();
- b_lines = false;
- }
- // interval covers current pixel and may be consequent pixels
- // draw them in one iteration
- glColorC(m_pCache->GetColorForScore(int_score));
- glRectd(pix, top_y - off_y, strip_end, bottom_y + off_y);
- }
- pix = strip_end;
- b_first = true;
- }
- //[start, end] specify part of the pixel covered by current score interval
- double start = max((double) pix, pix_start);
- double end = min((double) pix + 1, pix_end);
- double len = end - start;
- _ASSERT(len >= 0.0 && len <= 1.0);
- double d_score = len * int_score;
- if(b_first) { // new pixel - reset assign values to accumulators
- score_min = int_score;
- score_sum = d_score;
- score_len = len;
- b_first = false;
- } else { // accumulate
- score_min = min(score_min, int_score);
- score_sum += d_score;
- score_len += len;
- }
- if(pix_end < pix + 1) { // current range ends before current pixel
- if(it->GetToOpen() <= pos_end) { // advance score interval
- it++;
- b_new_interval = true;
- }
- if(chunk->GetAlnRange().GetToOpen() <= pos_end) { // advance chunk
- i_chunk++;
- }
- } else { // pixel is fully covered with current range - draw the pixel
- if(! b_lines) {
- glBegin(GL_LINES);
- b_lines = true;
- }
- double sc = score_sum / score_len;
- bool b_diff = (score_min != sc);
- glColorC(m_pCache->GetColorForScore(b_diff ? score_min : sc));
- glLined(pix, top_y - off_y, pix, bottom_y + off_y);
- if(b_diff) {
- glColorC(m_pCache->GetColorForScore(sc));
- glLined(pix, top_y - extr_off_y, pix, bottom_y + extr_off_y);
- }
- pix++;
- b_first = true;
- }
- }
- if(b_lines) {
- glEnd();
- }
- m_DList.End();
- }
- glTranslated(0.0, -rc_vp.Top(), 0.0);
- pane.Close();
- }
- #define SEQ_OFF_VERT 0
- #define SEQ_OFF_HORZ 0
- /// Checks if sequence can be drawn.
- bool CAlnVecRow::x_CanRenderSeq(CGlPane& pane)
- {
- if(m_pStyle) {
- double min_w = 1.0 / m_pStyle->GetSeqFont().GetMetric(CGlBitmapFont::eMetric_MaxCharWidth);
- double scale_x = pane.GetScaleX();
- return min_w >= scale_x;
- } else return false;
- }
- // renders a row of seq symbols in the range [Start, Stop]
- void CAlnVecRow::x_RenderSequence(CGlPane& pane, float y, int start, int stop)
- {
- _ASSERT(m_pStyle);
- string seq;
- m_Handle.GetAlnSeqString(seq, CAlnVec::TSignedRange(start, stop));
- replace(seq.begin(), seq.end(), '-', ' ');
- glColorC(m_pStyle->GetAlignTextColor());
- float x = start + 0.5 - pane.GetOffsetX();
- m_pStyle->GetSeqFont().ArrayTextOut(x, y, 1.0f, 0.0f, seq.c_str(),
- (float) pane.GetScaleX(), 0.0f);
- }
- static const int kTextOffsetY = 0;
- static const int kTextOffsetX = 2;
- static const int kPosOffsetX = 4;
- void CAlnVecRow::x_RenderDescr(CGlPane& pane, int state)
- {
- _ASSERT(m_pStyle);
- pane.OpenPixels();
- TVPRect rc_vp = pane.GetViewport();
- bool b_wid_focused = (state & fWidgetFocused) != 0;
- //draw background
- if(state & fItemSelected) {
- if(b_wid_focused) {
- glColorC(m_pStyle->GetSelBackFocusedColor());
- } else {
- glColorC(m_pStyle->GetSelBackColor());
- }
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glRectd(rc_vp.Left(), rc_vp.Bottom() - 1, rc_vp.Right(), rc_vp.Top());
- }
- // draw text label
- glColorC((state & fItemSelected) != 0 ? m_pStyle->GetSelTextColor()
- : m_pStyle->GetTextColor());
- int x = rc_vp.Left() + kTextOffsetX;
- int w = rc_vp.Width() - kTextOffsetX;
- m_pStyle->GetTextFont().TextOut(x, rc_vp.Top() - m_BaseHeight + 1, w,
- m_BaseHeight, m_Text.c_str(), FL_ALIGN_LEFT);
- // draw focus frame
- if(b_wid_focused && (state & fItemFocused) != 0) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glBegin(GL_LINE_LOOP);
- glVertex2d(rc_vp.Left(), rc_vp.Bottom());
- glVertex2d(rc_vp.Right(), rc_vp.Bottom());
- glVertex2d(rc_vp.Right(), rc_vp.Top());
- glVertex2d(rc_vp.Left(), rc_vp.Top());
- glEnd();
- }
- pane.Close();
- }
- void CAlnVecRow::x_RenderGraph(CGlPane& pane, CConstRef<CAlnVec::CAlnChunkVec> chunks)
- {
- if(m_bExpanded) {
- if( m_pGraph && m_pGraph->IsCreated()) {
- TModelUnit offset_y = pane.GetOffsetY();
- int y = (int) (pane.GetVisibleRect().Top() - offset_y) + m_BaseHeight;
- int h = m_Height - m_BaseHeight;
- m_pGraph->Render(pane, y, h, chunks);
- } else _ASSERT(false);
- }
- }
- const static int kButtonOffset = 2;
- const static int kButtonSize = 11;
- const static int kButtonSignSize = 7;
- /// Returns buttons bounds in screen coordinates, "pane" parameter specifies CGlPane
- /// corresponding to "Icons" column
- TVPRect CAlnVecRow::x_GetButtonRect(CGlPane& pane, EButtons btn)
- {
- const TVPRect& rc_vp = pane.GetViewport();
- int btn_space = kButtonSize + kButtonOffset;
- int x = rc_vp.Left() + kButtonOffset + ((int) btn) * btn_space;
- int y_top = rc_vp.Top() - (m_BaseHeight - kButtonSize) / 2;// kButtonOffset;
- TVPRect rc(x, y_top - kButtonSize + 1, x + kButtonSize - 1, y_top);
- return rc;
- }
- void CAlnVecRow::x_RenderIcons(CGlPane& pane)
- {
- _ASSERT(m_pStyle);
- pane.OpenPixels();
-
- glColorC(m_pStyle->GetTextColor());
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- // draw "Expand" button
- TVPRect rc_btn = x_GetButtonRect(pane, eExpand);
- glRectd(rc_btn.Left(), rc_btn.Bottom(), rc_btn.Right(), rc_btn.Top());
- if(IsExpandable()) {
- int offset = (kButtonSize - kButtonSignSize) / 2;
- TVPPoint pt_c = rc_btn.CenterPoint();
- // render "+" or "-"
- glBegin(GL_LINES);
- glVertex2d(rc_btn.Left() + offset, pt_c.Y());
- glVertex2d(rc_btn.Left() + offset + kButtonSignSize, pt_c.Y());
- if(! m_bExpanded) {
- glVertex2d(pt_c.X(), rc_btn.Bottom() + offset);
- glVertex2d(pt_c.X(), rc_btn.Bottom() + offset + kButtonSignSize);
- }
- glEnd();
- }
- if(m_pGraph && m_pGraph->HasData()) { // draw "Graph" button
- rc_btn = x_GetButtonRect(pane, eSetupGraphs);
- glRectd(rc_btn.Left(), rc_btn.Bottom(), rc_btn.Right(), rc_btn.Top());
- m_pStyle->GetTextFont().TextOut(rc_btn.Left() + 1, rc_btn.Bottom() + 1,
- kButtonSize - 2, kButtonSize - 2, "...", FL_ALIGN_CENTER);
- }
- // draw strand marker
- rc_btn = x_GetButtonRect(pane, eStrandMarker);
- int y_c = rc_btn.CenterPoint().Y();
- int half = rc_btn.Height() / 2;
- int x1 = rc_btn.Left();
- int x2 = rc_btn.Right();
- if(m_Handle.IsNegativeStrand()) {
- swap(x1, x2);
- }
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glColor3d(0.0, 0.5, 0.0);
- glBegin(GL_POLYGON);
- glVertex2d(x1, y_c - half);
- glVertex2d(x2, y_c);
- glVertex2d(x1, y_c + half);
- glEnd();
- pane.Close();
- }
- void CAlnVecRow::x_RenderStartPos(CGlPane& pane)
- {
- const TModelRect& rc_v = pane.GetVisibleRect();
- int aln_pos = (int) floor(rc_v.Left());
- x_RenderAlnPos(pane, aln_pos, CAlnVec::eRight);
- }
- void CAlnVecRow::x_RenderEndPos(CGlPane& pane)
- {
- const TModelRect& rc_v = pane.GetVisibleRect();
- int aln_pos = -1 + (int) ceil(rc_v.Right());
- x_RenderAlnPos(pane, aln_pos, CAlnVec::eLeft);
- }
- void CAlnVecRow::x_RenderSeqEnd(CGlPane& pane)
- {
- TSeqPos pos = m_Handle.GetBioseqHandle().GetBioseqLength() -1;
- x_RenderPos(pane, pos, "");
- }
- // generates text label for given position in alignment
- void CAlnVecRow::x_RenderAlnPos(CGlPane& pane, TSeqPos aln_pos, CAlnVec::ESearchDirection dir)
- {
- char *s_marker = "";
- int seq_pos = m_Handle.GetSeqPosFromAlnPos(aln_pos);
- if(seq_pos == -1) {
- seq_pos = m_Handle.GetSeqPosFromAlnPos(aln_pos, dir);
- switch(dir) {
- case CAlnVec::eRight: s_marker = ">> "; break;
- case CAlnVec::eLeft: s_marker = "<< "; break;
- default: break;
- }
- }
- x_RenderPos(pane, seq_pos, s_marker);
- }
- void CAlnVecRow::x_RenderPos(CGlPane& pane, TSeqPos pos, const char* s_marker)
- {
- _ASSERT(m_pStyle);
- pane.OpenPixels();
- const TVPRect& rc_vp = pane.GetViewport();
- // draw box
- glColorC(m_pStyle->GetFrameColor());
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glRectd(rc_vp.Left(), rc_vp.Bottom(), rc_vp.Right(), rc_vp.Top() + 1);
- string s_num = CTextUtils::FormatSeparatedNumber(pos + 1);
- string s_label(s_marker);
- s_label += s_num;
- glColorC(m_pStyle->GetTextColor());
- int x = rc_vp.Left() + kTextOffsetX;
- int w = rc_vp.Width() - kTextOffsetX * 3;
- m_pStyle->GetTextFont().TextOut(x, rc_vp.Top() - m_BaseHeight + 1, w, m_BaseHeight,
- s_label.c_str(), FL_ALIGN_RIGHT);
- pane.Close();
- }
- void CAlnVecRow::x_RenderEmptyBox(CGlPane& pane)
- {
- pane.OpenPixels();
- glColorC(m_pStyle->GetFrameColor());
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- TVPRect rc_vp = pane.GetViewport();
- glRectd(rc_vp.Left(), rc_vp.Bottom(), rc_vp.Right(), rc_vp.Top());
- pane.Close();
- }
- bool CAlnVecRow::IsExpandable() const
- {
- return m_pGraph->HasData();
- }
- bool CAlnVecRow::IsExpanded() const
- {
- return m_bExpanded;
- }
- void CAlnVecRow::Expand(bool b_exp)
- {
- if(IsExpandable() && IsExpanded() != b_exp) {
- m_bExpanded = b_exp;
- m_Height = m_BaseHeight;
- if(m_bExpanded) {
- x_CreateGraph();
- if(m_pGraph && m_pGraph->IsCreated()) {
- m_Height += m_pGraph->GetPreferredHeight();
- }
- } else x_DestroyGraph();
- if (x_GetHost()) {
- x_GetHost()->ARH_OnRowChanged(this);
- }
- }
- }
- const IAlnRowGraphProperties* CAlnVecRow::GetProperties() const
- {
- return m_pGraph ? m_pGraph->GetProperties() : NULL;
- }
- void CAlnVecRow::SetProperties(IAlnRowGraphProperties* props)
- {
- if(m_pGraph) {
- m_pGraph->SetProperties(props);
- }
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: align_row.cpp,v $
- * Revision 1000.5 2004/06/01 21:07:00 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.41
- *
- * Revision 1.41 2004/05/21 22:27:52 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.40 2004/05/10 17:46:35 yazhuk
- * Addressed GCC warnings
- *
- * Revision 1.39 2004/04/06 19:07:35 yazhuk
- * Added "EColumnType col_type" argument to GetHTMLActiveAreas(), added generation
- * of CHTMLActiveAreas for graphics in alignment
- *
- * Revision 1.38 2004/04/06 16:06:32 yazhuk
- * Removed _ASSERT from RenderColumn()
- *
- * Revision 1.37 2004/04/06 13:34:04 dicuccio
- * Formatting changes - trimmed trailing white space off of lines
- *
- * Revision 1.36 2004/04/02 17:13:31 yazhuk
- * Removed dumplicate 'const'
- *
- * Revision 1.35 2004/04/02 16:41:07 yazhuk
- * Rendering of strand indicator, clean-up
- *
- * Revision 1.34 2004/03/29 19:09:18 yazhuk
- * Added API for Graph properties access, CHTMLActiveArea-s generation,
- * eliminated m_TraceProxy
- *
- * Revision 1.33 2004/03/26 15:01:59 yazhuk
- * CTraceDataProxy class added
- *
- * Revision 1.32 2004/03/25 13:05:49 dicuccio
- * Use _TRACE() instead of cout
- *
- * Revision 1.31 2004/03/24 19:21:49 yazhuk
- * Lots of changes in data loading, tooltips.
- *
- * Revision 1.30 2004/03/18 17:10:19 yazhuk
- * Added API for expanding rows
- *
- * Revision 1.29 2004/03/16 15:37:22 vasilche
- * Added required include
- *
- * Revision 1.28 2004/03/11 17:50:41 dicuccio
- * Updated typedefs: dropped TDimension, TPosition, TIndex, TColor; use TSeqRange
- * instead of TRange
- *
- * Revision 1.27 2004/03/08 17:07:31 yazhuk
- * Replaced CTraceGraph with IAlnVecRowGraph interface; clean-up
- *
- * Revision 1.26 2004/03/08 15:44:23 yazhuk
- * Implemented creation of Trace Graphs from CSeq_graphs, refactored tooltips
- * generation and rendering
- *
- * Revision 1.25 2004/03/05 17:39:14 dicuccio
- * Use sequence::Getid() instead of CSeq_id::GetStringDescr()
- *
- * Revision 1.24 2004/03/02 15:12:21 yazhuk
- * Added support for Trace Graphs
- *
- * Revision 1.23 2004/02/17 15:19:10 yazhuk
- * Support for graphics caching
- *
- * Revision 1.22 2004/02/10 19:54:51 yazhuk
- * Redesigned alignment rendering, implemented scores averaging
- *
- * Revision 1.21 2004/01/08 19:44:04 yazhuk
- * Extended tooltips support
- *
- * Revision 1.20 2003/12/29 23:21:07 yazhuk
- * Added GetTooltip()
- *
- * Revision 1.19 2003/12/18 21:10:27 yazhuk
- * Redesigned CAlnVecRow - separated display style
- *
- * Revision 1.18 2003/12/08 15:15:45 yazhuk
- * Implemented workaround for OpenGL precision problems.
- *
- * Revision 1.17 2003/12/01 17:00:44 yazhuk
- * Migrated to using CGUIEvent
- *
- * Revision 1.16 2003/11/17 21:18:51 yazhuk
- * Refactored sequence rendering, replaced TextOut() with ArrayTextOut
- *
- * Revision 1.15 2003/11/03 16:50:41 yazhuk
- * Implemented event handling and support for expanding/collapsing alignment rows
- *
- * Revision 1.14 2003/10/29 23:33:23 yazhuk
- * Migrated to new classes, did a lot of refactoring
- *
- * Revision 1.13 2003/10/20 15:52:47 yazhuk
- * Changed colors.
- *
- * Revision 1.12 2003/10/15 21:27:07 yazhuk
- * Migrated from using CAlnVec to accessing data via "generic" interface in CAlignDataSource.
- *
- * Revision 1.11 2003/10/10 19:05:58 yazhuk
- * Implemented score coloring
- *
- * Revision 1.10 2003/10/08 14:17:25 dicuccio
- * use glColor3fv instead of glColorC
- *
- * Revision 1.9 2003/10/03 16:31:17 yazhuk
- * Fixed bug with closing CGlPane
- *
- * Revision 1.8 2003/09/29 13:44:46 yazhuk
- * Added "SeqEnd" column and functions for rendering "Start", "End" and "SeqEnd" columns
- *
- * Revision 1.7 2003/09/23 21:59:49 yazhuk
- * Changed color and adjusted text output position
- *
- * Revision 1.6 2003/09/14 14:03:44 ucko
- * #include <math.h> (needed with GCC)
- *
- * Revision 1.5 2003/09/10 20:39:04 yazhuk
- * Introduced notion of Columns
- *
- * Revision 1.4 2003/09/08 20:48:48 yazhuk
- * Suppressed "-" drawing for gaps
- *
- * Revision 1.3 2003/09/08 16:22:13 yazhuk
- * Drawing insertions, small improvements
- *
- * Revision 1.2 2003/09/02 16:53:57 yazhuk
- * GCC compilation fixes
- *
- * Revision 1.1 2003/08/28 18:25:28 yazhuk
- * Initial revision
- *
- * ===========================================================================
- */