alnmulti_renderer.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:19k
- /*
- * ===========================================================================
- * PRODUCTION $Log: alnmulti_renderer.cpp,v $
- * PRODUCTION Revision 1000.1 2004/06/01 21:07:11 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: alnmulti_renderer.cpp,v 1000.1 2004/06/01 21:07:11 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/ncbistl.hpp>
- #include <corelib/ncbitime.hpp>
- #include <gui/widgets/aln_multiple/alnmulti_renderer.hpp>
- #include <algorithm>
- BEGIN_NCBI_SCOPE
- static const int kRulerSpace = 4;
- static const int kMasterRowSpace = 4;
- CAlnMultiRenderer::CAlnMultiRenderer(const TVPRect& rc)
- : m_pContext(NULL),
- m_RulerAreaHeight(0),
- m_MasterAreaHeight(0),
- m_ListAreaHeight(0),
- m_bFocused(true)
- {
- m_RulerPane.EnableOffset();
- SetBackColor(CGlColor(0.95f, 1.0f, 0.95f)); //light green
- m_Ruler.SetHorizontal(true, CRuler::eTop);
- m_RulerAreaHeight = m_Ruler.GetPreferredSize().Y() + kRulerSpace;
- // setup columns
- AddColumn(120, "Description", IAlignRow::eDescr);
- AddColumn(40, "Icons", IAlignRow::eIcons);
- AddColumn(60, "Start", IAlignRow::eStart);
- AddColumn(0,"Alignment", IAlignRow::eAlignment, 1.0); // resizable, takes 100% of free space
- AddColumn(60, "End", IAlignRow::eEnd);
- AddColumn(60, "SeqEnd", IAlignRow::eSeqEnd);
- Resize(rc);
- }
- void CAlnMultiRenderer::SetContext(IAlnMultiRendererContext* p_context)
- {
- m_pContext = p_context;
- }
- void CAlnMultiRenderer::SetBackColor(const CGlColor Color)
- {
- m_BackColor = Color;
- }
- const CGlColor& CAlnMultiRenderer::GetBackColor() const
- {
- return m_BackColor;
- }
- CRuler& CAlnMultiRenderer::GetRuler()
- {
- return m_Ruler;
- }
- void CAlnMultiRenderer::Resize(const TVPRect& rc)
- {
- m_rcBounds = rc;
- x_LayoutColumns();
- x_Layout();
- }
- /// Graphics is rendered inthe current OpenGL context in the viewport defined
- /// by the / following rectangle
- /// (0, 0, m_rcBounds.Width() - 1, m_rcBounds.Height() - 1)
- void CAlnMultiRenderer::Render()
- {
- x_Render(NULL);
- }
- void CAlnMultiRenderer::Render(TAreaVector& areas)
- {
- x_Render(&areas);
- }
- void CAlnMultiRenderer::x_Render(TAreaVector* p_areas)
- {
- glClearColor(m_BackColor.GetRed(), m_BackColor.GetGreen(),
- m_BackColor.GetBlue(), m_BackColor.GetAlpha());
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- x_RenderRuler(p_areas);
- x_ResetRowListMap();
- x_RenderMasterRow();
- x_RenderItems(p_areas);
- x_PurgeRowListMap();
- }
- void CAlnMultiRenderer::Update()
- {
- x_Layout();
- m_RowToList.clear();
- }
- void CAlnMultiRenderer::SetRulerHeight(int height)
- {
- m_RulerAreaHeight = height;
- x_Layout();
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// protected members
- int CAlnMultiRenderer::GetListTop() const
- {
- return m_rcBounds.Height() - m_ListAreaHeight;
- }
- int CAlnMultiRenderer::GetColumnIndexByType(EColumnType type) const
- {
- int n_col = GetColumnsCount();
- for( int i = 0; i < n_col; i++ ) {
- if(m_vColumns[i].m_UserData == type)
- return i;
- }
- return -1;
- }
- TVPRect CAlnMultiRenderer::GetColumnRect(int i_col) const
- {
- const SColumn& Col = GetColumn(i_col);
- return TVPRect(Col.m_Pos, 0,
- Col.m_Pos + Col.m_Width -1, m_rcBounds.Height() - 1);
- }
- TVPRect CAlnMultiRenderer::GetColumnRect(EColumnType Type) const
- {
- int iCol = GetColumnIndexByType(Type);
- return GetColumnRect(iCol);
- }
- IAlignRow::EColumnType CAlnMultiRenderer::GetColumnTypeByIndex(int i_col) const
- {
- _ASSERT(i_col > -1);
- int type = (int) GetColumn(i_col).m_UserData;
- return (IAlignRow::EColumnType) type;
- }
- IAlignRow::EColumnType CAlnMultiRenderer::GetColumnTypeByX(int x) const
- {
- int i_col = CAlnMultiRenderer::GetColumnIndexByX(x);
- if(i_col >= 0) {
- int type = (int) GetColumn(i_col).m_UserData;
- return (IAlignRow::EColumnType) type;
- } else return IAlignRow::eInvalid;
- }
- void CAlnMultiRenderer::x_Layout()
- {
- m_MasterAreaHeight = kMasterRowSpace * 2;
- if(x_GetContext()) {
- IAlignRow* pRow = x_GetContext()->GetMasterRow();
- if(pRow)
- m_MasterAreaHeight += pRow->GetHeightPixels();
- }
- m_ListAreaHeight = GetVPListTop() + 1;
- }
- void CAlnMultiRenderer::x_RenderRuler(TAreaVector* p_areas)
- {
- if(m_RulerAreaHeight > 0) {
- int iAlign = GetColumnIndexByType(IAlignRow::eAlignment);
- const SColumn& col = GetColumn(iAlign);
- if(col.VisibleWidth()) {
- TVPUnit bot_y = m_ListAreaHeight + m_MasterAreaHeight;
- TVPUnit top_y = bot_y + m_RulerAreaHeight - 1;
- TVPRect rc_vp(col.m_Pos, bot_y, col.m_Pos + col.m_Width - 1, top_y);
- m_RulerPane.SetViewport(rc_vp);
- const CGlPane& port = x_GetContext()->GetAlignPort();
-
- TModelRect rcM = port.GetModelLimitsRect();
- rcM.SetVert(0, m_RulerAreaHeight - 1);
- m_RulerPane.SetModelLimitsRect(rcM);
-
- TModelRect rcV = port.GetVisibleRect();
- rcV.SetVert(0, m_RulerAreaHeight - 1);
- m_RulerPane.SetVisibleRect(rcV);
-
- m_Ruler.Render(m_RulerPane); // render
- if(p_areas) {
- CHTMLActiveArea area(CHTMLActiveArea::eLink, rc_vp,
- "Ruler", "Ruler", "");
- p_areas->push_back(area);
- }
- }
- }
- }
- void CAlnMultiRenderer::x_RenderMasterRow()
- {
- CGlPane pane(CGlPane::eNeverUpdate);
- pane.EnableOffset();
- TVPRect rc(0, m_ListAreaHeight);
- rc.SetSize(m_rcBounds.Width(), m_MasterAreaHeight);
- pane.SetViewport(rc);
- pane.OpenPixels();
- glColor3f(0.85f, 1.0f, 0.85f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glRecti(rc.Left(), rc.Bottom(), rc.Right(), rc.Top());
- pane.Close();
- int state = x_GetContext()->IsRendererFocused() ?
- IAlignRow::fWidgetFocused : IAlignRow::fNone;
- IAlignRow* p_row = x_GetContext()->GetMasterRow();
- if(p_row) {
- int H = p_row->GetHeightPixels();
- x_RenderRow(p_row, pane, state, rc.Bottom() + H + kMasterRowSpace, NULL);
- }
- }
- void CAlnMultiRenderer::x_RenderItems(TAreaVector* p_areas)
- {
- if(x_GetContext()) {
- // calculate visible range
- const CGlPane& port = x_GetContext()->GetAlignPort();
- TModelRect rcM = port.GetVisibleRect();
- int iFirst = x_GetContext()->GetLineByModelY((int) rcM.Top());
- iFirst = max(iFirst, 0);
- int iLast = x_GetContext()->GetLineByModelY((int) rcM.Bottom());
- iLast = (iLast == -1) ? x_GetContext()->GetLinesCount()-1 : iLast;
- if(iLast >= iFirst) {
- x_RenderItemsRange(iFirst, iLast, p_areas);
- }
- }
- }
- void CAlnMultiRenderer::x_RenderItemsRange(int iFirst, int iLast,
- TAreaVector* p_areas)
- {
- if(x_GetContext()) {
- const CGlPane& port = x_GetContext()->GetAlignPort();
- // create clipping rectangle
- TVPRect rc_clip = port.GetViewport();
- rc_clip.SetHorz(0, m_rcBounds.Width() - 1);
- if(rc_clip.Height() && rc_clip.Width()) {
- int y1 = GetVPListTop() + (int) port.GetVisibleRect().Top();
- const int base_state = m_bFocused ?
- IAlignRow::fWidgetFocused : IAlignRow::fNone;
- int i_focused = x_GetContext()->GetFocusedItemIndex();
- // create a single CGlPane for rendering all cells in all rows
- CGlPane pane(p_areas ? CGlPane::eAlwaysUpdate : CGlPane::eNeverUpdate);
- pane.EnableOffset();
- pane.SetClipRect(&rc_clip);
- for( int i = iFirst ; i <= iLast ; i++) {
- IAlignRow* p_row = x_GetContext()->GetRowByLine(i);
- int state = base_state;
- if(x_GetContext()->IsItemSelected(i))
- state |= IAlignRow::fItemSelected;
- if(i_focused == i)
- state |= IAlignRow::fItemFocused;
- int y = y1 - x_GetContext()->GetLinePosY(i);
- x_RenderRow(p_row, pane, state, y, p_areas);
- }
- pane.SetClipRect(NULL);
- }
- }
- }
- // renders all columns within the given Row, vp_top_y is OpenGL viewport
- // coordinate of the top pixel in the row
- void CAlnMultiRenderer::x_RenderRow(IAlignRow* p_row, CGlPane& pane,
- int state, int vp_top_y,
- TAreaVector* p_areas)
- {
- _ASSERT(p_row);
- m_RowToList[p_row] = true; // update "on-screen" attribute
- SetupPaneForRow(pane, p_row, vp_top_y);
- int col_n = GetColumnsCount();
- for( int i_col = 0; i_col < col_n; i_col++ ) {
- const SColumn& col = GetColumn(i_col);
- if(col.VisibleWidth()) {
- SetupPaneForColumn(pane, i_col);
- EColumnType type = x_GetColumnType(col);
- p_row->RenderColumn(type, pane, state);
- if(p_areas) {
- p_row->GetHTMLActiveAreas(type, pane, *p_areas);
- }
- }
- }
- }
- void CAlnMultiRenderer::SetupPaneForRow(CGlPane& pane,
- const IAlignRow* p_row,
- int vp_top_y) const
- {
- const CGlPane& port = x_GetContext()->GetAlignPort();
- int vp_bottom_y = vp_top_y - (p_row->GetHeightPixels() - 1);
- // setup model space
- TModelRect rcLim = port.GetModelLimitsRect();
- rcLim.SetVert(vp_top_y, vp_bottom_y);
- pane.SetModelLimitsRect(rcLim);
- TModelRect rcV = port.GetVisibleRect();
- rcV.SetVert(vp_top_y, vp_bottom_y);
- pane.SetVisibleRect(rcV);
- TVPRect rc_vp(0, vp_bottom_y, m_rcBounds.Width() - 1, vp_top_y);
- pane.SetViewport(rc_vp);
- }
- void CAlnMultiRenderer::SetupPaneForColumn(CGlPane& pane, int i_col) const
- {
- const SColumn& col = GetColumn(i_col);
- pane.GetViewport().SetHorz(col.m_Pos, col.m_Pos + col.m_Width - 1);
- }
- int CAlnMultiRenderer::GetVPListTop() const
- {
- return m_rcBounds.Height() - 1 - m_RulerAreaHeight - m_MasterAreaHeight;
- }
- int CAlnMultiRenderer::x_GetLineByWindowY(int WinY) const
- {
- int vpY = WinY - GetListTop();
- int OffsetY = (int) x_GetContext()->GetAlignPort().GetVisibleRect().Top();
- return x_GetContext()->GetLineByModelY(vpY + OffsetY);
- }
- TVPRect CAlnMultiRenderer::x_GetLineRect(int Index)
- {
- int Top = 0, H = 0;
- if(x_GetContext() && Index >= 0) {
- int OffsetY = (int) x_GetContext()->GetAlignPort().GetVisibleRect().Top();
- Top = x_GetContext()->GetLinePosY(Index) - OffsetY;
- H = x_GetContext()->GetLineHeight(Index);
- }
- return TVPRect(0, Top + H -1, m_rcBounds.Width() - 1, Top);
- }
- void CAlnMultiRenderer::x_ResetRowListMap()
- {
- NON_CONST_ITERATE(TRowToList, it, m_RowToList) {
- it->second = false;
- }
- }
- void CAlnMultiRenderer::x_PurgeRowListMap()
- {
- for( TRowToList::iterator it = m_RowToList.begin(); it != m_RowToList.end(); ) {
- if(! it->second) {
- //row is off-screen now - purge cached graphics
- (it->first)->GraphicsCacheCmd(IAlignRow::eDelete);
- TRowToList::iterator next = it;
- ++next;
- m_RowToList.erase(it);
- it = next;
- } else it++;
- }
- }
- const int kDefColumnWidth = 50;
- CAlnMultiRenderer::SColumn::SColumn()
- : m_Pos(0),
- m_Width(kDefColumnWidth),
- m_UserData(0),
- m_bVisible(true),
- m_Share(-1.0)
- {
- }
- int CAlnMultiRenderer::GetColumnsCount() const
- {
- return m_vColumns.size();
- }
- const CAlnMultiRenderer::SColumn& CAlnMultiRenderer::GetColumn(int index) const
- {
- _ASSERT(index >= 0 && index < (int) m_vColumns.size());
- return m_vColumns[index];
- }
- int CAlnMultiRenderer::AddColumn()
- {
- return AddColumn(kDefColumnWidth, "", 0);
- }
- int CAlnMultiRenderer::AddColumn(int width, const string& label, int data,
- double share)
- {
- int index = GetColumnsCount();
- return InsertColumn(index, width, label, data, share);
- }
- int CAlnMultiRenderer::InsertColumn(int index, int width, const string& label,
- int data, double share)
- {
- _ASSERT(index >= 0 && index <= (int) m_vColumns.size());
-
- SColumn col;
- col.m_Width = width;
- col.m_Label = label;
- col.m_UserData = data;
- col.m_Share = share;
- //###col.m_Pos = m_rcBounds.Width();
-
- TColumnVector::const_iterator it =
- m_vColumns.insert(m_vColumns.begin() + index, col);
- return it - m_vColumns.begin();
- }
- void CAlnMultiRenderer::SetColumnWidth(int index, int width)
- {
- _ASSERT(index >= 0 && index < (int) m_vColumns.size());
- _ASSERT(width >= 0);
- SColumn& col = m_vColumns[index];
- int delta = width - col.m_Width;
- col.m_Width = width;
-
- for( int i = index + 1; delta != 0 && i < (int) m_vColumns.size(); i++) {
- m_vColumns[i].m_Pos += delta;
- }
- }
- void CAlnMultiRenderer::SetColumnUserData(int index, int data)
- {
- _ASSERT(index >= 0 && index < (int) m_vColumns.size());
- m_vColumns[index].m_UserData = data;
- }
- void CAlnMultiRenderer::SetColumnVisible(int index, bool b_visible)
- {
- _ASSERT(index >= 0 && index < (int) m_vColumns.size());
- SColumn& col = m_vColumns[index];
- if(col.m_bVisible != b_visible) {
- col.m_bVisible = b_visible;
- int delta = b_visible ? col.m_Width : -col.m_Width;
- for( int i = index + 1; delta != 0 && i < (int) m_vColumns.size(); i++) {
- m_vColumns[i].m_Pos += delta;
- }
- }
- }
- int CAlnMultiRenderer::GetColumnIndexByX(int x) const
- {
- ITERATE(TColumnVector, it, m_vColumns) {
- if(x >= it->m_Pos && x < it->m_Pos + it->m_Width)
- return it - m_vColumns.begin();
- }
- return -1;
- }
- void CAlnMultiRenderer::UpdateColumns()
- {
- Resize(m_rcBounds);
- }
- void CAlnMultiRenderer::x_LayoutColumns()
- {
- int w = m_rcBounds.Width();
- int n_col = (int) m_vColumns.size();
- if(w > 0 && n_col > 0) { // resize all columns
- // getting statistics
- int total_w = 0;
- double total_share = 0.0; // sum of m_Share for all resizable columns
- int last_sh_index = -1; // index of last resizable column
- for( int j = 0; j < n_col; j++ ) {
- SColumn& col = m_vColumns[j];
- if(col.m_bVisible) {
- if(col.m_Share < 0.0) {
- total_w += col.m_Width;
- } else {
- total_share += col.m_Share;
- last_sh_index = j;
- }
- }
- }
- if(total_w < w) { // there is some space left for resizable columns
- int share_w = w - total_w;
- double K = share_w / total_share; // proportion
- int pos = 0, share_spent = 0;
- for( int j = 0; j < n_col; j++ ) {
- SColumn& col = m_vColumns[j];
- if(col.m_bVisible) {
- col.m_Pos = pos;
-
- if(col.m_Share >= 0.0) { // resizable column
- if(j == last_sh_index) {
- col.m_Width = share_w - share_spent; // the rest
- } else {
- col.m_Width = (int) (0.5 + share_w * K);
- share_spent += col.m_Pos;
- }
- }
- pos += col.m_Width;
- }
- }
- } else { // barely enough for fixed size columns
- int pos = 0;
- for( int j = 0; j < n_col; j++ ) {
- SColumn& col = m_vColumns[j];
- if(col.m_bVisible) {
- col.m_Pos = pos;
- if(col.m_Share >= 0.0) {
- col.m_Width = 0;
- }
- pos += col.m_Width;
- }
- }
- }
- }
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: alnmulti_renderer.cpp,v $
- * Revision 1000.1 2004/06/01 21:07:11 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
- *
- * Revision 1.12 2004/05/21 22:27:52 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.11 2004/05/10 17:46:35 yazhuk
- * Addressed GCC warnings
- *
- * Revision 1.10 2004/04/22 17:10:34 yazhuk
- * Fixed rendering of focus state
- *
- * Revision 1.9 2004/04/06 19:08:59 yazhuk
- * Added "TAreaVector* p_areas" argument ot x_RenderRuler, generation of
- * CHTMLActiveArea object for Ruler and alignment graphics
- *
- * Revision 1.8 2004/04/06 16:02:22 yazhuk
- * Added cloumns management API to CAlnMultiRenderer, eliminated CColumnWidget
- *
- * Revision 1.7 2004/04/06 13:37:09 dicuccio
- * Formatting changes - trimmed trailing white space
- *
- * Revision 1.6 2004/04/05 15:34:38 johnson
- * added a few consts to SetupPane methods
- *
- * Revision 1.5 2004/03/29 19:04:42 yazhuk
- * Support for CHTMLActiveArea-s generation
- *
- * Revision 1.4 2004/03/26 15:02:59 yazhuk
- * Changed width of "Icons" column
- *
- * Revision 1.3 2004/03/25 13:05:49 dicuccio
- * Use _TRACE() instead of cout
- *
- * Revision 1.2 2004/03/09 21:03:39 yazhuk
- * Clean-up
- *
- * Revision 1.1 2004/03/08 15:36:47 yazhuk
- * Initial revision
- *
- *
- * ===========================================================================
- */