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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: alnmulti_model.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 21:07:07  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: alnmulti_model.cpp,v 1000.1 2004/06/01 21:07:07 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 <gui/widgets/aln_multiple/alnmulti_model.hpp>
  41. #include <gui/widgets/aln_multiple/alnmulti_ds.hpp>
  42. BEGIN_NCBI_SCOPE
  43. USING_SCOPE(objects);
  44. ////////////////////////////////////////////////////////////////////////////////
  45. /// class CAlnMultiModel
  46. CAlnMultiModel::CAlnMultiModel()
  47. : m_pStyleCatalog(NULL),
  48.   m_pDataSource(NULL),
  49.   m_pMasterRow(NULL),
  50.   m_bAutoSort(false)
  51. {
  52.     double max_sym_w = 2 * m_Style.m_SeqFont.GetMetric(CGlBitmapFont::eMetric_MaxCharWidth);
  53.     // setup Port
  54.     m_Port.SetAdjustmentPolicy(CGlPane::fAdjustAll, CGlPane::fShiftToLimits);
  55.     m_Port.SetMinScaleX(1 / max_sym_w);
  56.     m_Port.SetOriginType(CGlPane::eOriginLeft, CGlPane::eOriginTop);
  57.         
  58.     SetPortLimits();
  59. }
  60. CAlnMultiModel::~CAlnMultiModel()
  61. {
  62.     ClearRows();
  63. }
  64. ////////////////////////////////////////////////////////////////////////////////
  65. // IAlnMultiPaneParent implementation
  66. void    CAlnMultiModel::SetStyleCatalog(const CRowStyleCatalog* catalog)
  67. {
  68.     m_pStyleCatalog = catalog;
  69. }
  70. const CWidgetDisplayStyle*  CAlnMultiModel::GetDisplayStyle() const
  71. {
  72.     return &m_Style;
  73. }
  74. int  CAlnMultiModel::GetRowState(TNumrow row)    const
  75. {
  76.     return x_GetRecordByRow(row).m_State;
  77. }
  78. bool    CAlnMultiModel::SRowRecord::PRecLineLess(const SRowRecord* rec1, 
  79.                                                  const SRowRecord* rec2)
  80. {
  81.     return rec1->m_Line < rec2->m_Line;
  82. }
  83. /// changes visibility state for given vector of rows to "b_visible"
  84. void    CAlnMultiModel::SetVisible(const vector<TNumrow>& rows, bool b_visible, 
  85.                                    bool b_invert_others)
  86. {
  87.     size_t n_rows = rows.size();
  88.     if(n_rows || b_invert_others) {
  89.         vector<TNumrow> v_items;              
  90.         TNumrow master_row = m_pDataSource->GetAnchor();
  91.     
  92.         if(b_invert_others) { // all rows in alignment are affected
  93.             // by default set state for all rows to "! b_visible"
  94.             vector<bool>    new_visible(m_RowToRec.size(), ! b_visible);
  95.             
  96.             ITERATE(vector<TNumrow>, it, rows)  {
  97.                 new_visible[*it] = b_visible;
  98.             }
  99.             vector<SRowRecord*> vis_recs;
  100.             vis_recs.reserve(b_visible ? rows.size() 
  101.                                                 : new_visible.size() - rows.size());
  102.             for( TNumrow row = 0; row < (TNumrow) new_visible.size(); row++ )    { // for all rows
  103.                 if(row != master_row  &&  new_visible[row])  { 
  104.                     SRowRecord& rec = x_GetRecordByRow(row);
  105.                     vis_recs.push_back(&rec);                
  106.                 }
  107.             }
  108.             // sort records by line number
  109.             sort(vis_recs.begin(), vis_recs.end(), SRowRecord::PRecLineLess);
  110.             
  111.             // copy row numbers to v_items
  112.             v_items.reserve(vis_recs.size());
  113.             ITERATE(vector<SRowRecord*>, it, vis_recs)  {
  114.                 IAlignRow* p_row = (*it)->m_pRow; 
  115.                 v_items.push_back(p_row->GetRowNum());
  116.             }
  117.             TNumrowModelImpl::SetItems(v_items, false, true);
  118.         }
  119.         else { // only "rows" will be affected
  120.             v_items.reserve(n_rows);
  121.             vector<TLine>   v_indices;
  122.             v_indices.reserve(n_rows);
  123.             ITERATE(vector<TNumrow>, it, rows)  {
  124.                 TNumrow row = *it;
  125.                 SRowRecord& rec = x_GetRecordByRow(row);
  126.                 bool b_old_vis = rec.IsVisible();
  127.                 if(b_old_vis != b_visible  &&  row != master_row)  { 
  128.                     // state needs to be changed
  129.                     TLine line = rec.m_Line;
  130.                     // clip line, it can be invalid
  131.                     line = min(line, (TLine) m_vVisibleRows.size()); 
  132.                     v_indices.push_back(line);
  133.                     if(b_visible) { 
  134.                         v_items.push_back(row);    
  135.                     }                
  136.                 }
  137.             }
  138.             if(b_visible) {
  139.                 TNumrowModelImpl::InsertItems(v_items, v_indices, false);
  140.             } else  { 
  141.                 TNumrowModelImpl::DeleteItems(v_indices, false);
  142.             }
  143.         }        
  144.         if(m_bAutoSort) {
  145.             x_DoUpdateRowsOrder(); // applying sorting        
  146.             x_DoUpdateRowPositions();
  147.         }
  148.                         
  149.         SetPortLimits();
  150.     }
  151. }
  152. CGlPane& CAlnMultiModel::GetAlignPort()
  153. {
  154.     return m_Port;
  155. }
  156. const CGlPane& CAlnMultiModel::GetAlignPort() const
  157. {
  158.     return m_Port;
  159. }
  160. CAlnMultiModel::TNumrow     CAlnMultiModel::GetLinesCount()
  161. {
  162.     return m_vVisibleRows.size();
  163. }
  164. int     CAlnMultiModel::GetFocusedItemIndex() const
  165. {
  166.     return SLM_GetFocusedItemIndex();
  167. }
  168. bool    CAlnMultiModel::IsItemSelected(int index) const
  169. {
  170.     return SLM_IsItemSelected(index);
  171. }
  172. IAlignRow*  CAlnMultiModel::GetRowByLine(int i_line)
  173. {
  174.     return x_GetRowByLine(i_line);
  175. }
  176. int     CAlnMultiModel::GetLineByRowNum(TNumrow row) const
  177. {
  178.     const CAlnMultiModel::SRowRecord& rec = x_GetRecordByRow(row);
  179.     return rec.IsVisible() ? rec.m_Line : -1;
  180. }
  181. IAlignRow*   CAlnMultiModel::GetMasterRow()
  182. {
  183.     return m_pMasterRow;
  184. }
  185. int     CAlnMultiModel::GetLineByModelY(int Y) const
  186. {
  187.     const TModelRect& rcL = m_Port.GetModelLimitsRect();
  188.     if(Y < rcL.Top()  || Y > rcL.Bottom())
  189.         return -1;
  190.     else {
  191.         vector<int>::const_iterator it = lower_bound(m_vVisibleRowPos.begin(), m_vVisibleRowPos.end(), Y);    
  192.         return it - m_vVisibleRowPos.begin() - 1;
  193.     }
  194. }
  195. int     CAlnMultiModel::GetLinePosY(int index) const
  196. {
  197.     return m_vVisibleRowPos[index];
  198. }
  199. int     CAlnMultiModel::GetLineHeight(TLine line) const
  200. {
  201.     return x_GetRowByLine(line)->GetHeightPixels();
  202. }
  203.     
  204. bool    CAlnMultiModel::IsRendererFocused()
  205. {
  206.     return true;
  207. }
  208. void CAlnMultiModel::ShowAll()
  209. {
  210.     vector<TNumrow> nothing;
  211.     SetVisible(nothing, false, true); // hide nothing and make other visible
  212. }
  213. void    CAlnMultiModel::EnableAutoSorting(bool b_en)
  214. {
  215.     m_bAutoSort = b_en;
  216. }
  217. void    CAlnMultiModel::UpdateSortOrder(void)
  218. {
  219.     m_bAutoSort = true;
  220.     
  221.     x_DoUpdateRowsOrder();
  222.     x_DoUpdateRowPositions();        
  223. }
  224. /// order can be changed only for visible rows, hidden will be ignored
  225. void    CAlnMultiModel::SetRowOrder(const vector<TNumrow>& rows, int pos)
  226. {
  227.     m_bAutoSort = false; // cancel auto sorting
  228.     int n_vis = m_vVisibleRows.size();
  229.     if(pos >= 0  &&  pos < n_vis)   {
  230.         vector<SRowRecord*> new_vis(n_vis, (SRowRecord*)NULL);
  231.         // new container to replace m_vVisibleRows
  232.         // move specified rows to new_order and replace them with NULL in m_vVisibleRows
  233.         int i = 0, line = pos;
  234.         for( ; i < (int) rows.size()  &&  line < n_vis; i++ )  {
  235.             TNumrow row = rows[i];
  236.             SRowRecord* p_rec = &x_GetRecordByRow(row);
  237.             if(p_rec->IsVisible())  {
  238.                 new_vis[line] = p_rec;
  239.                 m_vVisibleRows[p_rec->m_Line] = NULL; // remove from m_vVisibleRows
  240.                 line++;
  241.             }
  242.         }
  243.         // move the rest of the rows (those that are not NULL) preserving existing order
  244.         // move first "pos" elements and insert them before "pos" position
  245.         i = 0; // current postion in m_vVisibleRow
  246.         int ins_i = 0; // insertion position in new_vis
  247.         while(ins_i < pos)  {
  248.             for( ; m_vVisibleRows[i] == NULL  &&  i < n_vis; i++ )   { // skip                
  249.             }
  250.             _ASSERT(i < n_vis);
  251.             new_vis[ins_i++] = m_vVisibleRows[i++];
  252.         }
  253.         // copy the rest of rows to new_vis after "line"
  254.         ins_i = line;
  255.         while(ins_i < n_vis)    {
  256.             for( ; m_vVisibleRows[i] == NULL  &&  i < n_vis; i++ )   { // skip                
  257.             }
  258.             _ASSERT(i < n_vis);
  259.             new_vis[ins_i++] = m_vVisibleRows[i++];
  260.         }
  261.         
  262.         // assign new_vis to m_vVisibleRows
  263.         m_vVisibleRows = new_vis;
  264.         x_DoUpdateRowLines();
  265.         x_DoUpdateRowPositions();
  266.     }
  267. }
  268. void    CAlnMultiModel::SetDataSource(IAlnMultiDataSource* p_ds)
  269. {
  270.     m_pDataSource = p_ds;    
  271.     x_UpdateOnDataChanged(); // before it called Widget's version of function
  272. }
  273. ////////////////////////////////////////////////////////////////////////////////
  274. /// Update handlers
  275. void CAlnMultiModel::ClearRows()
  276. {
  277.     TNumrowModelImpl::DeleteAllItems();
  278.     NON_CONST_ITERATE(TRowToRecMap, it, m_RowToRec)  {
  279.         delete (*it)->m_pRow;
  280.         delete *it;
  281.     }
  282.     m_RowToRec.clear();
  283.     m_pMasterRow = NULL;
  284.     m_vVisibleRows.clear();
  285.     m_vVisibleRowPos.clear();
  286. }
  287. /// Creates IAlignRow objects for each row in the data source.
  288. void CAlnMultiModel::CreateRows()
  289. {
  290.     if(m_pDataSource)    {
  291.         _ASSERT(m_RowToRec.size() == 0  && m_pMasterRow == NULL);
  292.         const int aln_rows_n = m_pDataSource->GetNumRows();        
  293.         int pane_rows_n = aln_rows_n; // rows shown in align pane (Master row is not counted)
  294.                 
  295.         TNumrow MasterRow = -1;
  296.         if(m_pDataSource->IsSetAnchor())   {
  297.             MasterRow = m_pDataSource->GetAnchor();
  298.             --pane_rows_n;
  299.         }
  300.         
  301.         m_vVisibleRows.resize(pane_rows_n);
  302.         m_vVisibleRowPos.resize(pane_rows_n);
  303.                 
  304.         TLine i_line = 0;
  305.         m_RowToRec.resize(aln_rows_n);
  306.         for( TNumrow row = 0; row < aln_rows_n; row++ )    {
  307.             // call a factory method to create a row instance
  308.             IAlignRow* p_row = x_CreateRow(row); 
  309.             
  310.             SRowRecord* p_rec = new SRowRecord(p_row, i_line);
  311.             m_RowToRec[row] = p_rec;
  312.                 
  313.             if(row == MasterRow)    {
  314.                m_pMasterRow = p_row;
  315.                p_rec->SetState(IAlignRow::fItemHidden, true);
  316.             } else {
  317.                 m_vVisibleRows[i_line] = p_rec;
  318.                 i_line++;
  319.             } 
  320.         }
  321.         if(m_bAutoSort) {
  322.             x_DoUpdateRowsOrder(); // applying sorting
  323.         }
  324.         
  325.         // updating CSelListModelImpl
  326.         TNumrowModelImpl::TItemVector vItems(pane_rows_n);
  327.         for( size_t i = 0; i < m_vVisibleRows.size(); i++ ) {
  328.             vItems[i] = m_vVisibleRows[i]->m_pRow->GetRowNum();
  329.         } 
  330.         TNumrowModelImpl::SetItems(vItems, false, false);            
  331.         
  332.         x_DoUpdateRowPositions();        
  333.     }
  334. }
  335.   
  336. bool    CAlnMultiModel::x_SortRows()
  337. {
  338.     return true; // nothing has been changed
  339. }
  340. void    CAlnMultiModel::x_DoUpdateRowsOrder()
  341. {
  342.     _ASSERT(m_bAutoSort); // msut be called only when auto sorting is enabled
  343.     TIndex i_focused = SLM_GetFocusedItemIndex();        
  344.     const SRowRecord* p_rec = (i_focused >= 0) ? m_vVisibleRows[i_focused] : NULL;
  345.     if(x_SortRows())  {    
  346.         x_DoUpdateRowLines();
  347.         // restore focus
  348.         int line = p_rec ? p_rec->m_Line : -1;
  349.         SLM_FocusItem(line);
  350.     }
  351. }
  352. void    CAlnMultiModel::x_DoUpdateRowLines()
  353. {
  354.     for(size_t i = 0; i < m_vVisibleRows.size(); i++ )  {
  355.         SRowRecord& rec = *m_vVisibleRows[i];
  356.         rec.m_Line = i;
  357.     }
  358. }
  359. void    CAlnMultiModel::UpdateOnRowHChanged(void)
  360. {
  361.     x_DoUpdateRowPositions();
  362.     SetPortLimits();
  363. }
  364. /// recalculates vertical positions of row objects based on their order, 
  365. /// visibility and height
  366. void    CAlnMultiModel::x_DoUpdateRowPositions(void)
  367. {
  368.     int N = m_vVisibleRows.size();
  369.     m_vVisibleRowPos.resize(N);
  370.     
  371.     for( int  total_H = 0, i = 0; i < N; i++ )    {
  372.         IAlignRow* pRow = x_GetRowByLine(i);
  373.         m_vVisibleRowPos[i] = total_H;
  374.         total_H += pRow->GetHeightPixels();    
  375.     }
  376. }
  377. void CAlnMultiModel::SetPortLimits()
  378. {
  379.     if (m_pDataSource) {   
  380.         double Start = m_pDataSource->GetAlnStart();
  381.         double Stop = m_pDataSource->GetAlnStop();                
  382.         
  383.         double H = 0;
  384.         int iLast = m_vVisibleRows.size() - 1;
  385.         if(iLast > 0)
  386.             H = GetLinePosY(iLast) + GetLineHeight(iLast);
  387.         m_Port.SetModelLimitsRect(TModelRect(Start, H - 1, Stop + 1, 0));        
  388.     } else 
  389.     m_Port.SetModelLimitsRect(TModelRect(0, -1, 0, 0));        
  390. }
  391. void    CAlnMultiModel::SetMasterRow(TNumrow new_master_row)
  392. {
  393.     //Anchor the row to make it "Master"
  394.     m_pDataSource->SetAnchor(new_master_row);
  395.     
  396.     // rearrange Row objects and items
  397.     IAlignRow* pNewMaster = NULL;    
  398.     if(new_master_row != -1)    {     // remove row from the Align pane
  399.         SRowRecord& rec = x_GetRecordByRow(new_master_row);
  400.         pNewMaster = rec.m_pRow;
  401.         
  402.         rec.SetState(IAlignRow::fItemHidden, true);
  403.         vector<int> vDelItems;
  404.         vDelItems.push_back(rec.m_Line);
  405.         DeleteItems(vDelItems, false);
  406.     }
  407.     if(m_pMasterRow)    { // insert current Master into Align pane
  408.         TNumrow row = m_pMasterRow->GetRowNum();
  409.         SRowRecord& rec = x_GetRecordByRow(row);
  410.         TLine line = min(rec.m_Line, (TLine) m_vVisibleRows.size());
  411.         
  412.         rec.SetState(IAlignRow::fItemHidden, false);
  413.         InsertItem(line, m_pMasterRow->GetRowNum(), false);
  414.     }
  415.     
  416.     m_pMasterRow = pNewMaster;    
  417.     
  418.     if(m_bAutoSort) {
  419.         x_DoUpdateRowsOrder(); // applying sorting    
  420.     }    
  421.     x_DoUpdateRowPositions();    
  422.     
  423.     SetPortLimits(); // set new limits
  424. }
  425. void    CAlnMultiModel::x_UpdateOnDataChanged()
  426. {
  427.     ClearRows();
  428.     if (m_pDataSource) {               
  429.         CreateRows();
  430.         SetPortLimits();
  431.     }
  432. }
  433. IAlignRow*  CAlnMultiModel::x_GetRowByLine(int index)
  434. {
  435.     _ASSERT(index >= 0 && (size_t) index < m_vVisibleRows.size());
  436.     SRowRecord* p_rec = m_vVisibleRows[index];
  437.     return static_cast<IAlignRow*>(p_rec->m_pRow);
  438. }
  439. const IAlignRow*  CAlnMultiModel::x_GetRowByLine(int index) const
  440. {
  441.     _ASSERT(index >= 0  &&  (size_t) index < m_vVisibleRows.size());
  442.     SRowRecord* p_rec = m_vVisibleRows[index];
  443.     return static_cast<IAlignRow*>(p_rec->m_pRow);
  444. }
  445. ////////////////////////////////////////////////////////////////////////////////
  446. // CSelListModelImpl virtual functions
  447. void   CAlnMultiModel::x_SelectItem(TIndex index, bool b_sel)
  448. {
  449.     m_vVisibleRows[index]->SetState(IAlignRow::fItemSelected, b_sel);
  450. }
  451. bool   CAlnMultiModel::x_IsItemSelected(TIndex index) const
  452. {
  453.     return m_vVisibleRows[index]->IsSelected();
  454. }
  455. // returns number of visible rows (lines)
  456. CAlnMultiModel::TIndex CAlnMultiModel::x_GetItemsCount()   const
  457. {
  458.     return m_vVisibleRows.size(); 
  459. }
  460. CAlnMultiModel::TItem   CAlnMultiModel::x_GetItem(TIndex index)    const
  461. {
  462.     TNumrow row = x_GetRowByLine(index)->GetRowNum();
  463.     return row;
  464. }
  465. void    CAlnMultiModel::x_SetEntries(const TEntryVector& v_entries)
  466. {
  467.     size_t entries_n = v_entries.size();
  468.     m_vVisibleRows.resize(entries_n);
  469.     for( size_t i = 0; i < entries_n; i++ ) {
  470.         TNumrow row = v_entries[i].first;
  471.         SRowRecord& rec = *m_RowToRec[row];
  472.         rec.m_Line = i;
  473.         rec.SetState(IAlignRow::fItemSelected, v_entries[i].second);
  474.         rec.SetState(IAlignRow::fItemHidden, false);
  475.         m_vVisibleRows[i] = &rec;
  476.     }
  477. }
  478. CAlnMultiModel::TIndex CAlnMultiModel::x_GetItemIndex(const TItem& item)
  479. {
  480.     SRowRecord& rec = *m_RowToRec[item];
  481.     return rec.IsVisible() ? rec.m_Line : -1;
  482. }
  483. void   CAlnMultiModel::x_InsertItem(TIndex index, const TItemEntry& entry)
  484. {
  485.     TNumrow row = entry.first;
  486.     SRowRecord* p_rec = m_RowToRec[row];
  487.     p_rec->SetState(IAlignRow::fItemSelected, entry.second);
  488.     p_rec->m_Line = index;
  489.     m_vVisibleRows.insert(m_vVisibleRows.begin() + index, p_rec);
  490. }
  491. void    CAlnMultiModel::x_CompleteInsertion()
  492. {
  493.     x_DoUpdateRowLines();
  494. }
  495. void   CAlnMultiModel::x_MarkItemForErase(TIndex index)
  496. {
  497.     m_vVisibleRows[index]->SetState(IAlignRow::fItemHidden, true);
  498.     m_vVisibleRows[index]->SetState(IAlignRow::fItemSelected, false);
  499.     m_vVisibleRows[index] = NULL;
  500. }
  501. void   CAlnMultiModel::x_EraseMarkedItems()
  502. {
  503.     int shift = 0;
  504.     int count = m_vVisibleRows.size();
  505.     for(int i = 0; i < count; i++ ) {
  506.         if(m_vVisibleRows[i])   {
  507.             if(shift >0)    {
  508.                 m_vVisibleRows[i - shift] = m_vVisibleRows[i];
  509.                 m_vVisibleRows[i - shift]->m_Line = i - shift;
  510.             }
  511.         } else   shift++;
  512.     }
  513.     m_vVisibleRows.resize(m_vVisibleRows.size() - shift);
  514. }
  515. void   CAlnMultiModel::x_ClearItems()
  516. {
  517.     for( size_t i = 0; i < m_vVisibleRows.size(); i++ ) {
  518.         m_vVisibleRows[i]->SetState(IAlignRow::fItemHidden, true);
  519.         m_vVisibleRows[i]->SetState(IAlignRow::fItemSelected, false);
  520.     }
  521.     m_vVisibleRows.clear();
  522. }
  523. END_NCBI_SCOPE
  524. /*
  525.  * ===========================================================================
  526.  * $Log: alnmulti_model.cpp,v $
  527.  * Revision 1000.1  2004/06/01 21:07:07  gouriano
  528.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  529.  *
  530.  * Revision 1.11  2004/05/21 22:27:52  gorelenk
  531.  * Added PCH ncbi_pch.hpp
  532.  *
  533.  * Revision 1.10  2004/05/10 17:46:35  yazhuk
  534.  * Addressed GCC warnings
  535.  *
  536.  * Revision 1.9  2004/04/27 15:36:28  yazhuk
  537.  * Fixed SetVisivle() so that it does not change rows order
  538.  *
  539.  * Revision 1.8  2004/04/23 14:09:13  johnson
  540.  * removed invalid ASSERT
  541.  *
  542.  * Revision 1.7  2004/04/22 17:09:41  yazhuk
  543.  * Enable Auto Sorting from UpdateSortOrder()
  544.  *
  545.  * Revision 1.6  2004/04/06 19:38:11  dicuccio
  546.  * Tweak for GCC - cast NULL to pointer type for vector<*>
  547.  *
  548.  * Revision 1.5  2004/04/06 16:04:05  yazhuk
  549.  * Implemented GetSelectedRows(), EnableAutoSorting(), SetRowOrder()
  550.  *
  551.  * Revision 1.4  2004/04/02 16:39:42  yazhuk
  552.  * Selection/visibility handling fixes
  553.  *
  554.  * Revision 1.3  2004/03/18 17:08:26  yazhuk
  555.  * Modified SetVisible() to support "b_invert_others" argument
  556.  *
  557.  * Revision 1.2  2004/03/17 20:15:37  yazhuk
  558.  * Refactored CAlnMultiModel interface
  559.  *
  560.  * Revision 1.1  2004/03/09 20:59:14  yazhuk
  561.  * Initial revision. Factored out from CAlnMultiWidget.
  562.  *
  563.  * ===========================================================================
  564.  */