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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: pager.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:15:56  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.39
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: pager.cpp,v 1000.2 2004/06/01 19:15:56 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.  * Author:  Eugene Vasilchenko, Anton Golikov
  35.  *
  36.  */
  37. #include <ncbi_pch.hpp>
  38. #include <corelib/ncbistd.hpp>
  39. #include <cgi/ncbicgi.hpp>
  40. #include <html/pager.hpp>
  41. BEGIN_NCBI_SCOPE
  42. const string CPager::KParam_PageSize      = "dispmax";
  43. const string CPager::KParam_ShownPageSize = "showndispmax";
  44. const string CPager::KParam_DisplayPage   = "page";
  45. const string CPager::KParam_Page          = "page ";
  46. const string CPager::KParam_PreviousPages = "previous pages";
  47. const string CPager::KParam_NextPages     = "next pages";
  48. const string CPager::KParam_InputPage     = "inputpage";
  49. CPager::CPager(const CCgiRequest& request,
  50.                int pageBlockSize,
  51.                int defaultPageSize,
  52.                EPagerView view /* = eImage */)
  53.     : m_PageSize(GetPageSize(request, defaultPageSize)),
  54.       m_PageBlockSize(max(1, pageBlockSize)),
  55.       m_PageChanged(false), m_view(view)
  56. {
  57.     const TCgiEntries& entries = request.GetEntries();
  58.     
  59.     if ( IsPagerCommand(request) ) {
  60.         // look in preprocessed IMAGE values with empty string key
  61.         TCgiEntriesCI i = entries.find(NcbiEmptyString);
  62.         if (i != entries.end()) {
  63.             const string& value = i->second;
  64.             if (value == KParam_PreviousPages) {
  65.                 // previous pages
  66.                 // round to previous page block
  67.                 m_PageChanged = true;
  68.                 int page = GetDisplayedPage(request);
  69.                 m_DisplayPage = page - page % m_PageBlockSize - 1;
  70.             }
  71.             else if (value == KParam_NextPages) {
  72.                 // next pages
  73.                 // round to next page block
  74.                 m_PageChanged = true;
  75.                 int page = GetDisplayedPage(request);
  76.                 m_DisplayPage = page - page % m_PageBlockSize +
  77.                     m_PageBlockSize;
  78.             }
  79.             else if ( NStr::StartsWith(value, KParam_Page) ) {
  80.                 // look for params like: "page 2"
  81.                 string page = value.substr(KParam_Page.size());
  82.                 try {
  83.                     m_DisplayPage = NStr::StringToInt(page) - 1;
  84.                     m_PageChanged = true;
  85.                 } catch (exception& _DEBUG_ARG(e)) {
  86.                     _TRACE( "Exception in CPager::CPager: " << e.what() );
  87.                     m_PageChanged = false;
  88.                 }
  89.             }
  90.         }
  91.         i = entries.find(KParam_InputPage);
  92.         if (i != entries.end()) {
  93.             try {
  94.                 m_DisplayPage = NStr::StringToInt(i->second) - 1;
  95.                 m_DisplayPage = max(m_DisplayPage, 0);
  96.                 m_PageChanged = true;
  97.             } catch (exception& _DEBUG_ARG(e)) {
  98.                 _TRACE( "Exception in CPager::IsPagerCommand: " << e.what() );
  99.                 m_PageChanged = false;
  100.             }
  101.         }
  102.     } else {
  103.         try {
  104.             m_PageChanged = true;
  105.             int page = GetDisplayedPage(request);
  106.             TCgiEntriesCI oldPageSize = entries.find(KParam_ShownPageSize);
  107.             if( !page || oldPageSize == entries.end() )
  108.                 throw runtime_error("Error getting page params");
  109.             //number of the first element in old pagination
  110.             int oldFirstItem = page * NStr::StringToInt( oldPageSize->second );
  111.             m_DisplayPage = oldFirstItem / m_PageSize;
  112.         } catch(exception& _DEBUG_ARG(e)) {
  113.             _TRACE( "Exception in CPager::CPager: " << e.what() );
  114.             m_DisplayPage = 0;
  115.             m_PageChanged = false;
  116.         }
  117.          
  118.     }
  119.     if( !m_PageChanged )
  120.             m_DisplayPage = GetDisplayedPage(request);
  121.     m_PageBlockStart = m_DisplayPage - m_DisplayPage % m_PageBlockSize;
  122. }
  123. bool CPager::IsPagerCommand(const CCgiRequest& request)
  124. {
  125.     TCgiEntries& entries = const_cast<TCgiEntries&>(request.GetEntries());
  126.     // look in preprocessed IMAGE values with empty string key
  127.     TCgiEntriesI i = entries.find(NcbiEmptyString);
  128.     if (i != entries.end()) {
  129.         const string& value = i->second.GetValue();
  130.         if (value == KParam_PreviousPages) {
  131.             // previous pages
  132.             return true;
  133.         }
  134.         else if (value == KParam_NextPages) {
  135.             // next pages
  136.             return true;
  137.         }
  138.         else if ( NStr::StartsWith(value, KParam_Page) ) {
  139.             // look for params like: "page 2"
  140.             string page = value.substr(KParam_Page.size());
  141.             try {
  142.                 NStr::StringToInt(page);
  143.                 return true;
  144.             } catch (exception& _DEBUG_ARG(e)) {
  145.                 _TRACE( "Exception in CPager::IsPagerCommand: " << e.what() );
  146.             }
  147.         }
  148.     }
  149.     i = entries.find(KParam_InputPage);
  150.     if (i != entries.end()) {
  151.         try {
  152.             NStr::StringToInt(i->second.GetValue());
  153.             return true;
  154.         } catch (exception& _DEBUG_ARG(e)) {
  155.             _TRACE( "Exception in CPager::IsPagerCommand: " << e.what() );
  156.         }
  157.     }
  158.     return false;
  159. }
  160. int CPager::GetDisplayedPage(const CCgiRequest& request)
  161. {
  162.     const TCgiEntries& entries = request.GetEntries();
  163.     TCgiEntriesCI entry = entries.find(KParam_DisplayPage);
  164.     if (entry != entries.end()) {
  165.         try {
  166.             int displayPage = NStr::StringToInt(entry->second);
  167.             if ( displayPage >= 0 )
  168.                 return displayPage;
  169.             _TRACE( "Negative page start in CPager::GetDisplayedPage: " <<
  170.                     displayPage );
  171.         } catch (exception& _DEBUG_ARG(e)) {
  172.             _TRACE( "Exception in CPager::GetDisplayedPage " << e.what() );
  173.         }
  174.     }
  175.     // use default page start
  176.     return 0;
  177. }
  178. int CPager::GetPageSize(const CCgiRequest& request, int defaultPageSize)
  179. {
  180.     TCgiEntries& entries = const_cast<TCgiEntries&>(request.GetEntries());
  181.     TCgiEntriesCI entry;
  182.     
  183.     if( IsPagerCommand(request) ) {
  184.         entry = entries.find(KParam_ShownPageSize);
  185.     } else {
  186.         entry = entries.find(KParam_PageSize);
  187.     }
  188.     if (entry != entries.end()) {
  189.         try {
  190.             string dispMax = entry->second;
  191.             int pageSize = NStr::StringToInt(dispMax);
  192.             if( pageSize > 0 ) {
  193.                 //replace dispmax for current page size
  194.                 entries.erase(KParam_PageSize);
  195.                 entries.insert(TCgiEntries::value_type(KParam_PageSize,
  196.                                                        dispMax));
  197.                 return pageSize;
  198.             }
  199.             _TRACE( "Nonpositive page size in CPager::GetPageSize: " <<
  200.                     pageSize );
  201.         } catch (exception& _DEBUG_ARG(e)) {
  202.             _TRACE( "Exception in CPager::GetPageSize " << e.what() );
  203.         }
  204.     }
  205.     // use default page size
  206.     return defaultPageSize;
  207. }
  208. void CPager::SetItemCount(int itemCount)
  209. {
  210.     m_ItemCount = itemCount;
  211.     if (m_DisplayPage * m_PageSize >= itemCount) {
  212.         m_DisplayPage = 0;
  213.     }
  214. }
  215. pair<int, int> CPager::GetRange(void) const
  216. {
  217.     int firstItem = m_DisplayPage * m_PageSize;
  218.     return pair<int, int>(firstItem, min(firstItem + m_PageSize, m_ItemCount));
  219. }
  220. void CPager::CreateSubNodes(void)
  221. {
  222.     AppendChild(new CHTML_hidden(KParam_ShownPageSize, m_PageSize));
  223.     AppendChild(new CHTML_hidden(KParam_DisplayPage, m_DisplayPage));
  224. }
  225. CNCBINode* CPager::GetPageInfo(void) const
  226. {
  227.     if (m_ItemCount <= m_PageSize) {
  228.         return 0;
  229.     }
  230.     int lastPage = (m_ItemCount - 1) / m_PageSize;
  231.     return new CHTMLPlainText(
  232.         "Page " + NStr::IntToString(m_DisplayPage + 1) +
  233.         " of " + NStr::IntToString(lastPage + 1));
  234. }
  235. CNCBINode* CPager::GetItemInfo(void) const
  236. {
  237.     CHTML_div* node = new CHTML_div;
  238.     node->SetClass("medium2");
  239.     
  240.     if (m_ItemCount == 0) {
  241.         node->AppendChild(new CHTMLPlainText("0 items found"));
  242.     } else {
  243.         int firstItem = m_DisplayPage * m_PageSize + 1;
  244.         int endItem = min((m_DisplayPage + 1) * m_PageSize, m_ItemCount);
  245.         if (firstItem != endItem) {
  246.             node->AppendChild(new CHTMLPlainText("Items " +
  247.                                                  NStr::IntToString(firstItem)
  248.                                                  + "-" +
  249.                                                  NStr::IntToString(endItem)));
  250.         } else {
  251.             node->AppendChild(new CHTMLPlainText("Item " +
  252.                                                  NStr::IntToString(firstItem))
  253.                               );
  254.         }
  255.         node->AppendChild(new CHTMLPlainText(" of " +
  256.                                              NStr::IntToString(m_ItemCount)));
  257.     }
  258.     return node;
  259. }
  260. CNCBINode* CPager::GetPagerView(const string& imgDir,
  261.                                 const int imgX, const int imgY,
  262.                                 const string& js_suffix /*kEmptyStr*/) const
  263. {
  264.     if (m_ItemCount <= m_PageSize) {
  265.         return 0;
  266.     }
  267.     switch (m_view) {
  268.     case eButtons:
  269.         return new CPagerViewButtons(*this, js_suffix);
  270.     default:
  271.         break;
  272.     }
  273.     // Default old behavor
  274.     return new CPagerView(*this, imgDir, imgX, imgY);
  275. }
  276. CPagerView::CPagerView(const CPager& pager, const string& imgDir,
  277.                        const int imgX, const int imgY)
  278.     : m_ImagesDir(imgDir), m_ImgSizeX(imgX), m_ImgSizeY(imgY), m_Pager(pager)
  279. {
  280.     return;
  281. }
  282. void CPagerView::AddImageString(CNCBINode* node, int number,
  283.                                 const string& prefix, const string& suffix)
  284. {
  285.     string s = NStr::IntToString(number + 1);
  286.     string name = CPager::KParam_Page + s;
  287.     CHTML_image* img;
  288.     for ( size_t i = 0; i < s.size(); ++i ) {
  289.         img = new CHTML_image(name, m_ImagesDir + prefix + s[i] + suffix, 0);
  290.         img->SetAttribute("Alt", name);
  291.         if ( m_ImgSizeX )
  292.             img->SetWidth( m_ImgSizeX );
  293.         if ( m_ImgSizeY )
  294.             img->SetHeight( m_ImgSizeY );
  295.         node->AppendChild( img );
  296.     }
  297. }
  298. void CPagerView::AddInactiveImageString(CNCBINode* node, int number,
  299.                                         const string& prefix,
  300.                                         const string& suffix)
  301. {
  302.     string s = NStr::IntToString(number + 1);
  303.     CHTML_img* img;
  304.     for ( size_t i = 0; i < s.size(); ++i ) {
  305.         img = new CHTML_img(m_ImagesDir + prefix + s[i] + suffix);
  306.         img->SetAttribute("Alt", s);
  307.         if( m_ImgSizeX )
  308.             img->SetWidth( m_ImgSizeX );
  309.         if( m_ImgSizeY )
  310.             img->SetHeight( m_ImgSizeY );
  311.         node->AppendChild( img );
  312.     }
  313. }
  314. void CPagerView::CreateSubNodes()
  315. {
  316.     int column         = 0;
  317.     int pageSize       = m_Pager.m_PageSize;
  318.     int blockSize      = m_Pager.m_PageBlockSize;
  319.     int currentPage    = m_Pager.m_DisplayPage;
  320.     int itemCount      = m_Pager.m_ItemCount;
  321.     int firstBlockPage = currentPage - currentPage % blockSize;
  322.     int lastPage       = max(0, (itemCount + pageSize - 1) / pageSize - 1);
  323.     int lastBlockPage  = min(firstBlockPage + blockSize - 1, lastPage);
  324.     if (firstBlockPage > 0) {
  325.         CHTML_image* img = new CHTML_image(CPager::KParam_PreviousPages,
  326.                                            m_ImagesDir + "prev.gif", 0);
  327.         img->SetAttribute("Alt", CPager::KParam_PreviousPages);
  328.         if ( m_ImgSizeX )
  329.             img->SetWidth( m_ImgSizeX );
  330.         if ( m_ImgSizeY )
  331.             img->SetHeight( m_ImgSizeY );
  332.         InsertAt(0, column++, img);
  333.     }
  334.     for (int i = firstBlockPage; i <= lastBlockPage ; ++i) {
  335.         if (i == currentPage) {
  336.             // current link
  337.             AddImageString(Cell(0, column++), i, "black_", ".gif");
  338.         }
  339.         else {
  340.             // normal link
  341.             AddImageString(Cell(0, column++), i, "", ".gif");
  342.         }
  343.     }
  344.     if (lastPage != lastBlockPage) {
  345.         CHTML_image* img = new CHTML_image(CPager::KParam_NextPages,
  346.                                            m_ImagesDir + "next.gif", 0);
  347.         img->SetAttribute("Alt", CPager::KParam_NextPages);
  348.         if ( m_ImgSizeX )
  349.             img->SetWidth( m_ImgSizeX );
  350.         if ( m_ImgSizeY )
  351.             img->SetHeight( m_ImgSizeY );
  352.         InsertAt(0, column++, img);
  353.     }
  354. }
  355. CPagerViewButtons::CPagerViewButtons(const CPager& pager, const string& js_suffix)
  356.     : m_Pager(pager), m_jssuffix(js_suffix)
  357. {
  358. }
  359. void CPagerViewButtons::CreateSubNodes()
  360. {
  361.     int column      = 0;
  362.     int pageSize    = m_Pager.m_PageSize;
  363.     int currentPage = m_Pager.m_DisplayPage;
  364.     int itemCount   = m_Pager.m_ItemCount;
  365.     int lastPage    = max(0, (itemCount + pageSize - 1) / pageSize - 1);
  366.     if (currentPage > 0) {
  367.         CHTML_a* prev = new CHTML_a("javascript:var frm = " 
  368.                                     "document.frmQueryBox; " 
  369. "frm.inputpage.value=" +
  370.                                     NStr::IntToString(currentPage) + 
  371.                                     "; Go('Pager');", "Previous");
  372.         prev->SetClass("dblinks");
  373.         InsertAt(0, column, prev);
  374.         InsertAt(0, column++, new CHTML_nbsp);
  375.     }
  376.         
  377.     CHTML_input* butt = new CHTML_input("BUTTON", "GoToPage");
  378.     butt->SetClass("dblinks");
  379.     butt->SetAttribute("value", "Page");
  380.     butt->SetEventHandler(eHTML_EH_Click,
  381.                           "form.cmd.value='';form." +
  382.                           CPager::KParam_InputPage +
  383.                           ".value=form.textpage" + m_jssuffix +
  384.                           ".value;Go('Pager');");
  385.     InsertAt(0, column, butt);
  386.     InsertAt(0, column, new CHTML_nbsp);
  387.     CHTML_input* textpage =  new CHTML_text("textpage" + m_jssuffix, 4,
  388.                                          NStr::IntToString(currentPage + 1));
  389.     textpage->SetClass("dblinks");
  390.     
  391.     string suffix;
  392.     if ( m_jssuffix.empty() ) {
  393.        suffix = "1";
  394.     }
  395.     
  396.     textpage->SetEventHandler(eHTML_EH_Change,
  397.   "if(form.textpage" + suffix + "){form.textpage"
  398.                               + suffix +".value=" + "this.value}");
  399.     
  400.     textpage->SetEventHandler(eHTML_EH_KeyPress,
  401.                               "form." + CPager::KParam_InputPage +".value=" 
  402.   "this.value;KeyPress('Pager',event);");
  403.                                          
  404.     InsertAt(0, column++, textpage);
  405.     CHTML_div* div = new CHTML_div;
  406.     div->SetClass("medium2");
  407.     div->AppendChild(new CHTML_nbsp);
  408.     div->AppendChild(new CHTMLPlainText("of"));
  409.     div->AppendChild(new CHTML_nbsp);
  410.     div->AppendChild(new CHTMLPlainText(NStr::IntToString(lastPage + 1)));
  411.     InsertAt(0, column++, div);
  412.     
  413.     // place holder for page num, to explicitly tell about new page num
  414.     InsertAt(0, column++, new CHTML_hidden(CPager::KParam_InputPage +
  415.                                            m_jssuffix, kEmptyStr));
  416.     if (currentPage < lastPage) {
  417.         CHTML_a* next = new CHTML_a("javascript:var frm = " 
  418.                                     "document.frmQueryBox;" 
  419. "frm.inputpage.value=" +
  420.                                     NStr::IntToString(currentPage + 2) + 
  421.                                     ";Go('Pager');", "Next");
  422.         next->SetClass("dblinks");
  423.         InsertAt(0, column, next);
  424.         InsertAt(0, column++, new CHTML_nbsp(2));
  425.     }
  426. }
  427. END_NCBI_SCOPE
  428. /*
  429.  * ===========================================================================
  430.  * $Log: pager.cpp,v $
  431.  * Revision 1000.2  2004/06/01 19:15:56  gouriano
  432.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.39
  433.  *
  434.  * Revision 1.39  2004/05/17 20:59:50  gorelenk
  435.  * Added include of PCH ncbi_pch.hpp
  436.  *
  437.  * Revision 1.38  2003/11/03 17:03:08  ivanov
  438.  * Some formal code rearrangement. Move log to end.
  439.  *
  440.  * Revision 1.37  2003/10/02 18:24:38  ivanov
  441.  * Get rid of compilation warnings; some formal code rearrangement
  442.  *
  443.  * ===========================================================================
  444.  */