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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: sel_list_model_impl.hpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:51:49  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef GUI_WIDGETS_ALN_MULTIPLE___SEL_LIST_MODEL_IMPL__HPP
  10. #define GUI_WIDGETS_ALN_MULTIPLE___SEL_LIST_MODEL_IMPL__HPP
  11. /*  $Id: sel_list_model_impl.hpp,v 1000.1 2004/06/01 19:51:49 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Authors:  Andrey Yazhuk
  37.  *
  38.  * File Description:
  39.  *
  40.  */
  41. #include <corelib/ncbistl.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <gui/widgets/aln_multiple/list_mvc.hpp>
  44. BEGIN_NCBI_SCOPE
  45. ////////////////////////////////////////////////////////////////////////////////
  46. /// CSelListModelImpl provides a defult implementation of ISelListModel.
  47. ///
  48. /// m_iFocusedItem and m_iAnchor item are not updated automatically.
  49. template <class Item>
  50. class CSelListModelImpl : public ISelListModel<Item>
  51. {
  52. public:
  53.     typedef typename ISelListModel<Item>::TItem        TItem;
  54.     typedef typename ISelListModel<Item>::TIndex       TIndex;
  55.     typedef typename ISelListModel<Item>::TIndexVector TIndexVector;
  56.     
  57.     typedef vector<TItem>                    TItemVector;
  58.     
  59.     /// related interfaces
  60.     ///
  61.     typedef ISelListView<TItem>     TSelListView;
  62.     typedef ISelListModel<TItem>    TSelListModel;
  63.     // ISelListModel interface implementation
  64.     virtual TIndex  SLM_GetItemsCount() const;
  65.     virtual TItem   SLM_GetItem(TIndex index) const;
  66.     
  67.     virtual TIndex  SLM_GetFocusedItemIndex() const;
  68.     virtual bool    SLM_IsItemSelected(TIndex index) const;
  69.     virtual TIndex  SLM_GetSelectedCount() const;
  70.     virtual void    SLM_GetSelectedIndices(TIndexVector& vIndices) const;
  71.     virtual void    SLM_GetSelectedItems(TItemVector& items) const;
  72.     virtual void    SLM_FocusItem(TIndex index);    
  73.     
  74.     virtual void    SLM_SelectSingleItem(TIndex index);    
  75.     virtual void    SLM_InvertSingleItem(TIndex index);    
  76.     virtual void    SLM_SelectItems(const TIndexVector& vIndeces,
  77.                                     bool b_reset_others = false);
  78.     virtual void    SLM_SelectAll(bool bSelect = true);
  79.     virtual void    SLM_SelectTo(TIndex index);
  80.     
  81.     virtual void    SLM_AddSLView(TSelListView* pView);
  82.     virtual void    SLM_RemoveSLView(TSelListView* pView);
  83. protected:
  84.     CSelListModelImpl();
  85.     void    SetItems(const TItemVector& vItems, bool b_update, 
  86.                      bool b_keep_selection = false);
  87.     bool    InsertItem(TIndex index, const TItem& item, bool b_update);
  88.     void    InsertItems(const TItemVector& v_items, const TIndexVector& v_indices,
  89.                         bool b_update);    
  90.     
  91.     bool    DeleteItem(TIndex index, bool bUpdate = true);    
  92.     void    DeleteItems(const TIndexVector& vIndices, bool b_update);    
  93.     void    DeleteAllItems();
  94. protected:
  95.     typedef pair<TItem, bool>   TItemEntry;  // bool for "Selected" state
  96.     typedef vector<TItemEntry>  TEntryVector;
  97.     typedef map<TItem, int>     TItemToIndexMap;    
  98.     typedef list<TSelListView*> TViewList;
  99.     
  100.     virtual void    x_SelectItem(TIndex index, bool b_sel) = 0;
  101.     virtual bool    x_IsItemSelected(TIndex index) const = 0;
  102.     virtual TIndex  x_GetItemsCount()   const = 0;
  103.     virtual TItem   x_GetItem(TIndex index)    const = 0;
  104.     virtual void    x_SetEntries(const TEntryVector& v_entries) = 0;
  105.     virtual TIndex  x_GetItemIndex(const TItem& item) = 0;
  106.     
  107.     /// inserts item, but does not updates all data structures
  108.     virtual void    x_InsertItem(TIndex index, const TItemEntry& entry) = 0;
  109.     /// performs update after all items have been inserted
  110.     virtual void    x_CompleteInsertion() = 0; 
  111.     /// mark item for deletion
  112.     virtual void    x_MarkItemForErase(TIndex index) = 0;
  113.     /// deletes all marked items in a single pass, performs neccessary updates
  114.     virtual void    x_EraseMarkedItems() = 0;
  115.     virtual void    x_ClearItems() = 0;
  116.     /// TODO 
  117.     void            x_EraseItem(TIndex index)
  118.     {
  119.         // TODO 
  120.         _ASSERT(false);
  121.     }
  122. protected:
  123.     
  124.     void  x_Clear();
  125.     void  x_GetSelectedItems(TIndexVector& vIndices);
  126.     void  x_ViewsUpdateItems(TIndexVector &vIndices);
  127.     void  x_ViewsUpdateItemRange(int iStart, int iEnd);
  128. protected: // data members
  129.     int     m_SelectedCount;
  130.     int     m_iFocusedItem;
  131.     int     m_iAnchorItem;
  132.     TViewList   m_lsViews;
  133. };
  134. ////////////////////////////////////////////////////////////////////////////////
  135. ///  class CSelListModelImpl
  136. template<class Item>   
  137.     CSelListModelImpl<Item>::CSelListModelImpl()
  138. : m_SelectedCount(0),
  139.     m_iFocusedItem(-1),
  140.     m_iAnchorItem(-1)
  141. {
  142. }
  143. template<class Item>   
  144.     typename CSelListModelImpl<Item>::TIndex     CSelListModelImpl<Item>::SLM_GetItemsCount() const
  145. {
  146.     return x_GetItemsCount();
  147. }
  148. template<class Item>   
  149.     typename CSelListModelImpl<Item>::TItem   CSelListModelImpl<Item>::SLM_GetItem(TIndex index) const
  150. {
  151.     return x_GetItem(index);
  152. }
  153. template<class Item>   
  154.     typename CSelListModelImpl<Item>::TIndex     CSelListModelImpl<Item>::SLM_GetFocusedItemIndex() const
  155. {
  156.     return m_iFocusedItem;
  157. }
  158. template<class Item>   
  159.     bool    CSelListModelImpl<Item>::SLM_IsItemSelected(TIndex index) const
  160. {
  161.     return x_IsItemSelected(index);
  162. }
  163. template<class Item>   
  164.     typename CSelListModelImpl<Item>::TIndex    CSelListModelImpl<Item>::SLM_GetSelectedCount() const
  165. {
  166.     return m_SelectedCount;
  167. }
  168. template<class Item>   
  169.     void    CSelListModelImpl<Item>::SLM_GetSelectedIndices(TIndexVector& vIndices) const
  170. {
  171.     size_t size = x_GetItemsCount();
  172.     for( size_t i = 0;  i < size;  i++ ) {
  173.         if (x_IsItemSelected(i))    {
  174.             vIndices.push_back(i);
  175.         }
  176.     }
  177. }
  178. template<class Item>   
  179.     void   CSelListModelImpl<Item>:: SLM_GetSelectedItems(TItemVector& items) const
  180. {
  181.     size_t size = x_GetItemsCount();
  182.     for( size_t i = 0;  i < size;  i++ ) {
  183.         if (x_IsItemSelected(i))    {
  184.             TItem item = x_GetItem(i);
  185.             items.push_back(item);
  186.         }
  187.     }
  188. }
  189. template<class Item>   
  190.     void    CSelListModelImpl<Item>::SLM_FocusItem(TIndex index)
  191. {
  192.     if (index != m_iFocusedItem)   {
  193.         TIndexVector vUpdateItems;
  194.         vUpdateItems.push_back(m_iFocusedItem); // update old focus
  195.         m_iFocusedItem = index;
  196.         vUpdateItems.push_back(m_iFocusedItem); // update new one
  197.         x_ViewsUpdateItems(vUpdateItems);
  198.     }
  199. }
  200.     
  201. template<class Item>   
  202.     void    CSelListModelImpl<Item>::SLM_SelectSingleItem(TIndex index)
  203. {
  204.     TIndexVector vPrevSel;
  205.     x_GetSelectedItems(vPrevSel);
  206.     if(m_iFocusedItem != index) {
  207.         if(m_iFocusedItem >= 0  &&  ! x_IsItemSelected(m_iFocusedItem))
  208.             vPrevSel.push_back(m_iFocusedItem); // if it is not selected - we need update it separately
  209.         m_iFocusedItem = index;
  210.     }
  211.     for(size_t i = 0; i < vPrevSel.size(); i++ )  { // reset selection
  212.         TIndex index = vPrevSel[i];
  213.         x_SelectItem(index, false);
  214.     }
  215.     if( index > -1) {
  216.         x_SelectItem(index, true);
  217.         vPrevSel.push_back(index);
  218.         m_iAnchorItem = index;
  219.         m_SelectedCount = 1;
  220.     } else m_SelectedCount = 0;
  221.     x_ViewsUpdateItems(vPrevSel);
  222. }
  223. template<class Item>   
  224.     void    CSelListModelImpl<Item>::SLM_InvertSingleItem(TIndex index)
  225. {
  226.     TIndexVector vIndices;
  227.     if( index > -1) {
  228.         if(m_iFocusedItem != index) {
  229.             vIndices.push_back(m_iFocusedItem);
  230.             m_iFocusedItem = index;
  231.         }
  232.         bool b_old_sel = x_IsItemSelected(index);
  233.         x_SelectItem(index, ! b_old_sel);
  234.         vIndices.push_back(index);
  235.         m_iAnchorItem = index;
  236.         m_SelectedCount += b_old_sel ? -1 : 1;
  237.     } else m_SelectedCount = 0;
  238.     x_ViewsUpdateItems(vIndices);
  239. }
  240. /// Select items with given indices. If "b_invert_others" == "true" - deselects 
  241. /// all other items.
  242. template<class Item>   
  243.     void    CSelListModelImpl<Item>::SLM_SelectItems(const TIndexVector& vIndices,
  244.                                                      bool b_reset_others)
  245. {
  246.     if(b_reset_others)     {
  247.         int n_items = x_GetItemsCount();
  248.         vector<bool> v_sel(n_items, false);
  249.         for( size_t i = 0;  i < vIndices.size();  i++ ) {
  250.             v_sel[vIndices[i]] = true;   
  251.         }
  252.         for( size_t j= 0; j < n_items;  j++ )   {
  253.             x_SelectItem(j, v_sel[j]);
  254.         }
  255.         m_SelectedCount = vIndices.size();
  256.         x_ViewsUpdateItemRange(0, n_items - 1);
  257.     } else {
  258.         TIndexVector vUpdateIndices;
  259.         ITERATE(typename TIndexVector, it, vIndices) {
  260.             if ( ! x_IsItemSelected(*it)) {
  261.                 x_SelectItem(*it, true);
  262.                 vUpdateIndices.push_back(*it);
  263.             }
  264.         }
  265.         m_SelectedCount += vUpdateIndices.size();
  266.         
  267.         x_ViewsUpdateItems(vUpdateIndices);
  268.     }
  269. }
  270. template<class Item>   
  271.     void    CSelListModelImpl<Item>::SLM_SelectAll(bool b_select)
  272. {
  273.     TIndex count = x_GetItemsCount();
  274.     for( TIndex i = 0; i < count; i++ )  {
  275.         x_SelectItem(i, b_select);
  276.     }
  277.     m_SelectedCount = b_select ? count : 0;
  278.     
  279.     if(count)
  280.         x_ViewsUpdateItemRange(0, count - 1);
  281. }
  282. template<class Item>   
  283.     void    CSelListModelImpl<Item>::SLM_SelectTo(TIndex index)
  284. {
  285.     if(m_iAnchorItem<0) 
  286.         m_iAnchorItem = 0;
  287.     TIndex iStart = min(m_iAnchorItem, index);
  288.     TIndex iEnd = max(m_iAnchorItem, index);
  289.     // reset old selection and select from iStart to iEnd
  290.     TIndexVector vUpdateIndices;
  291.     bool bPrevFocusedChanged = false;
  292.     TIndex count = x_GetItemsCount();
  293.     
  294.     for( TIndex i = 0; i < count;  i++ )   {
  295.         bool b_select = (i >= iStart && i <= iEnd);
  296.         if (x_IsItemSelected(i) != b_select)
  297.         {
  298.             x_SelectItem(i, b_select);
  299.             m_SelectedCount += b_select ? 1 : -1;
  300.             vUpdateIndices.push_back(i);
  301.             if(i == m_iFocusedItem) 
  302.                 bPrevFocusedChanged = true;
  303.         }
  304.     }
  305.     if(m_iFocusedItem != index)
  306.     {
  307.         if( ! bPrevFocusedChanged)
  308.             vUpdateIndices.push_back(m_iFocusedItem); // need to update
  309.         m_iFocusedItem = index;
  310.     }
  311.     
  312.     vector<TIndex> gopa;
  313.     x_GetSelectedItems(gopa); //### debug
  314.     x_ViewsUpdateItems(vUpdateIndices);
  315. }
  316. template<class Item>   
  317.     void  CSelListModelImpl<Item>::SLM_AddSLView(TSelListView* pView)
  318. {
  319.     if( find(m_lsViews.begin(), m_lsViews.end(), pView) == m_lsViews.end()) {
  320.         m_lsViews.push_back(pView);
  321.         pView->SLV_SetModel(static_cast<TSelListModel*>(this));
  322.     }
  323. }
  324. template<class Item>   
  325.     void  CSelListModelImpl<Item>::SLM_RemoveSLView(TSelListView* pView)
  326. {
  327.   typename TViewList::iterator itView
  328.       = find( m_lsViews.begin(), m_lsViews.end(), pView);
  329.   if (itView != m_lsViews.end())  {
  330.     m_lsViews.erase(itView);
  331.     pView->SLV_SetModel(NULL);
  332.   }
  333. }
  334. template<class Item>   
  335.     void  CSelListModelImpl<Item>::SetItems(const TItemVector& vItems,
  336.                                          bool b_update, bool b_keep_selection)
  337. {
  338.     size_t items_n = vItems.size();    
  339.     TEntryVector v_entries(items_n);
  340.     int n = x_GetItemsCount();
  341.     int n_sel = 0;
  342.     for(  size_t i = 0;  i < items_n; i++) {
  343.         v_entries[i].first = vItems[i];            
  344.         bool b_sel = false;
  345.         if(b_keep_selection)    {
  346.             TIndex index = x_GetItemIndex(vItems[i]);
  347.             b_sel = (index > -1  && index < n) ? x_IsItemSelected(index) : false;
  348.         }
  349.         v_entries[i].second = b_sel;
  350.         if(b_sel)   {
  351.             n_sel++;
  352.         }
  353.     }
  354.     x_Clear();
  355.     x_SetEntries(v_entries);
  356.     m_SelectedCount = n_sel;
  357.     
  358.     if(b_update)    {
  359.         TIndex i_max = max(0, (int) items_n - 1);
  360.         x_ViewsUpdateItemRange(0, i_max);
  361.     }
  362. }
  363. template<class Item>   
  364.     void    CSelListModelImpl<Item>::InsertItems(const TItemVector& v_items, 
  365.                                                  const TIndexVector& v_indices, 
  366.                                                  bool b_update)
  367. {
  368.     size_t n_items = v_items.size();
  369.     _ASSERT(n_items == v_indices.size());
  370.     
  371.     TIndex i_min = x_GetItemsCount();
  372.     for( size_t i = 0; i <  n_items;  i++ )     {
  373.         TIndex ind = v_indices[i];
  374.         ind = min(ind, x_GetItemsCount());
  375.         x_InsertItem(ind, TItemEntry(v_items[i], false));
  376.         
  377.         i_min = min(i_min, ind);
  378.     }
  379.     x_CompleteInsertion();
  380.     if(b_update)    {
  381.         TIndex i_max = max(0, x_GetItemsCount() - 1);
  382.         x_ViewsUpdateItemRange(i_min, i_max);
  383.     }
  384. }
  385. template<class Item>   
  386.     bool    CSelListModelImpl<Item>::InsertItem(TIndex index, const TItem& item,
  387.                                                 bool b_update)
  388. {
  389.     if(index >= 0  &&  index <= x_GetItemsCount())  {
  390.         x_InsertItem(index, TItemEntry(item, false));
  391.         x_CompleteInsertion();
  392.         if(b_update)    {
  393.             TIndex i_max = max(0, x_GetItemsCount() - 1);
  394.             x_ViewsUpdateItemRange(index, i_max);
  395.         }
  396.         return true;
  397.     }   
  398.     return false;
  399. }
  400. template<class Item>   
  401.     void    CSelListModelImpl<Item>::DeleteItems(const TIndexVector& vIndices,
  402.                                                  bool bUpdate)
  403. {
  404.     TIndex count = x_GetItemsCount();
  405.     TIndex min_del = count;
  406.     
  407.     ITERATE(typename TIndexVector, it, vIndices)  {
  408.         TIndex index = *it;
  409.         if(index >= 0  &&  index < count)  {
  410.             if(m_iFocusedItem == index)
  411.                 m_iFocusedItem = -1;
  412.             if(m_iAnchorItem == index)
  413.                 m_iAnchorItem = m_iFocusedItem;
  414.             if(x_IsItemSelected(index))    //item selected
  415.             {
  416.                 x_SelectItem(index, false);
  417.                 m_SelectedCount--;  
  418.             }
  419.             x_MarkItemForErase(index);
  420.             min_del = min(index, count);
  421.         }
  422.    }
  423.    x_EraseMarkedItems();
  424.    if(bUpdate  &&  min_del < count)    {
  425.         x_ViewsUpdateItemRange(min_del, count-1);
  426.    }
  427. }
  428. template<class Item>   
  429.     bool    CSelListModelImpl<Item>::DeleteItem(TIndex index, bool bUpdate)
  430. {
  431.     TIndex count = x_GetItemsCount();
  432.     if(index >= 0  &&  index < count)  {
  433.         if(m_iFocusedItem == index)
  434.             m_iFocusedItem = -1;
  435.         if(m_iAnchorItem == index)
  436.             m_iAnchorItem = m_iFocusedItem;
  437.         if(x_IsItemSelected(index))    //item selected
  438.             m_SelectedCount--;  
  439.         x_EraseItem(index);
  440.         if (bUpdate)    {
  441.             TIndex i_max = max(0, count -1);
  442.             x_ViewsUpdateItemRange(0, i_max);
  443.         }
  444.         return true;
  445.     }
  446.     return false;
  447. }
  448. template<class Item>   
  449.     void  CSelListModelImpl<Item>::DeleteAllItems()
  450. {
  451.     x_Clear();
  452.     x_ViewsUpdateItemRange(0, -1);
  453. }
  454. template<class Item>   
  455.     void  CSelListModelImpl<Item>::x_Clear()
  456. {
  457.     x_ClearItems();
  458.     m_iFocusedItem = m_iAnchorItem = -1;
  459.     m_SelectedCount = 0;
  460. }
  461. template<class Item>   
  462.     void  CSelListModelImpl<Item>::x_GetSelectedItems(TIndexVector& vIndices)
  463. {
  464.     vIndices.reserve(m_SelectedCount);
  465.     TIndex count = x_GetItemsCount();
  466.     for( TIndex i = 0; i < count;  i++ ) {
  467.         if(x_IsItemSelected(i))
  468.             vIndices.push_back(i);
  469.     }
  470.     _ASSERT(vIndices.size() == (size_t) m_SelectedCount);
  471. }
  472. template<class Item>   
  473.     void  CSelListModelImpl<Item>::x_ViewsUpdateItems(TIndexVector &vIndices)
  474. {
  475.     NON_CONST_ITERATE(typename TViewList, itView, m_lsViews)
  476.         (*itView)->SLV_UpdateItems(vIndices);
  477. }
  478. template<class Item>   
  479.     void  CSelListModelImpl<Item>::x_ViewsUpdateItemRange(int iStart, int iEnd)
  480. {
  481.     NON_CONST_ITERATE(typename TViewList, itView, m_lsViews)
  482.         (*itView)->SLV_UpdateRange(iStart, iEnd);
  483. }
  484. END_NCBI_SCOPE
  485. /*
  486.  * ===========================================================================
  487.  * $Log: sel_list_model_impl.hpp,v $
  488.  * Revision 1000.1  2004/06/01 19:51:49  gouriano
  489.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  490.  *
  491.  * Revision 1.13  2004/04/26 17:31:53  ucko
  492.  * Add explicit "typename" annotations required by GCC 3.4.
  493.  *
  494.  * Revision 1.12  2004/04/06 15:26:57  yazhuk
  495.  * Added SLM_GetSelectedItems()
  496.  *
  497.  * Revision 1.11  2004/04/02 16:23:09  yazhuk
  498.  * Added bool b_reset_others to SLM_SelectItems() function; bugfixes
  499.  * >
  500.  *
  501.  * Revision 1.10  2004/03/24 19:49:08  gorelenk
  502.  * Added dummy x_EraseItem .
  503.  *
  504.  * Revision 1.9  2004/03/22 14:41:37  gorelenk
  505.  * Fixed compilation errors.
  506.  *
  507.  * Revision 1.8  2004/01/08 19:38:09  yazhuk
  508.  * Bugfixes, clean-up
  509.  *
  510.  * Revision 1.7  2003/12/29 23:20:38  yazhuk
  511.  * Minor bugfix
  512.  *
  513.  * Revision 1.6  2003/12/22 16:38:32  yazhuk
  514.  * Added InsertItems() for bulk inserting; reformatted code, added comments
  515.  *
  516.  * Revision 1.5  2003/12/19 20:25:39  ucko
  517.  * Also explicitly carry over TIndexVector for the sake of MIPSpro.
  518.  *
  519.  * Revision 1.4  2003/12/19 14:05:40  dicuccio
  520.  * Attempt to fix errors on MIPS/Solaris - carry base class typedefs forward
  521.  *
  522.  * Revision 1.3  2003/12/18 22:18:34  yazhuk
  523.  * Workshop problems fixes
  524.  *
  525.  * Revision 1.2  2003/12/18 21:17:21  yazhuk
  526.  * Converted CSelListModelImpl to template class
  527.  *
  528.  * Revision 1.1  2003/12/18 20:55:39  yazhuk
  529.  * Initial revision
  530.  *
  531.  * ===========================================================================
  532.  */
  533. #endif  // GUI_WIDGETS_ALN_MULTIPLE___SEL_LIST_MODEL_IMPL__HPP