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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: menu_item.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 21:29:16  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.6
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: menu_item.cpp,v 1000.0 2004/06/01 21:29:16 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.  */
  37. #include <ncbi_pch.hpp>
  38. #include <corelib/ncbistd.hpp>
  39. #include <gui/widgets/fl/menu_item.hpp>
  40. #include <FL/fl_draw.H>
  41. BEGIN_NCBI_SCOPE
  42. ////////////////////////////////////////////////////////////////////////////////
  43. // CMenuItem
  44. CMenuItem::CMenuItem()
  45. : m_ItemNode(this)
  46. {
  47.     Init(eSeparator);
  48. }
  49. CMenuItem::CMenuItem(const string& label, const string& image_alias)
  50. : m_ItemNode(this)
  51. {
  52.     Init(eSubmenu, label, eCmdNone, image_alias);
  53. }
  54. CMenuItem::CMenuItem(const string& label, TCmdID cmd, const string& image_alias, int state)
  55. : m_ItemNode(this)
  56. {
  57.     Init(eItem, label, cmd, image_alias, state);
  58. }
  59. CMenuItem::CMenuItem(EType type, const string& label, TCmdID cmd, const string& image_alias, int state)
  60. : m_ItemNode(this)
  61. {
  62.     Init(type, label, cmd, image_alias, state);
  63. }
  64. ///copy contsructor - copes just attributes, not the subitems
  65. CMenuItem::CMenuItem(const CMenuItem& item)
  66. : m_ItemNode(this)
  67. {
  68.     Init(item.m_Type, item.m_Label, item.m_CommandID, item.m_ImageAlias, item.m_State);
  69. }
  70. CMenuItem::~CMenuItem()
  71. {
  72.     for( TItemNode::TNodeList_I it = m_ItemNode.SubNodeBegin();
  73.         it != m_ItemNode.SubNodeEnd();  )   {
  74.         TItemNode::TNodeList_I it2 = it++;
  75.         TItemNode* node = m_ItemNode.DetachNode(*it2);    
  76.         delete node->GetValue();
  77.     }
  78. }
  79. void    CMenuItem::Init(EType type, const string& label, TCmdID cmd, 
  80.                         const string& image_alias, int state)
  81. {
  82.     m_Type = type;
  83.     m_Label = label;
  84.     m_CommandID = cmd;
  85.     m_ImageAlias = image_alias;
  86.     m_State = state;
  87. }
  88. void    CMenuItem::InitPopup(const string& label, const string& image_alias)
  89. {
  90.     Init(eSubmenu, label, eCmdNone, image_alias);
  91. }
  92. void    CMenuItem::InitItem(const string& label, TCmdID cmd, const string& image_alias, int state)
  93. {
  94.     Init(eItem, label, cmd, image_alias, state);
  95. }
  96. void    CMenuItem::InitSeparator()
  97. {
  98.     Init(eSeparator);
  99. }
  100. bool    CMenuItem::Equal(const CMenuItem& item) const
  101. {
  102.     return m_Type == item.m_Type  &&  m_Label == item.m_Label  
  103.             &&  m_CommandID == item.m_CommandID  && m_ImageAlias == item.m_ImageAlias;
  104. }
  105. CMenuItem*  CMenuItem::Clone() const
  106. {
  107.     CMenuItem* p_clone = new CMenuItem(*this);
  108.     for(TChildItem_CI    it = SubItemsBegin();  it != SubItemsEnd(); it++ )  {
  109.        CMenuItem* p_subitem = (*it)->GetValue();
  110.        p_clone->AddSubItem(p_subitem->Clone());
  111.     }
  112.     return p_clone;
  113. }
  114. CMenuItem::EType   CMenuItem::GetType()   const
  115. {
  116.     return m_Type;
  117. }
  118. void    CMenuItem::SetType(EType type)
  119. {
  120.     m_Type = type;
  121. }
  122. bool    CMenuItem::IsItem()    const
  123. {
  124.     return m_Type == eItem;
  125. }
  126. bool    CMenuItem::IsSubmenu() const
  127. {
  128.     return m_Type == eSubmenu;
  129. }
  130. bool    CMenuItem::IsSeparator() const
  131. {
  132.     return m_Type == eSeparator;
  133. }
  134. const string&   CMenuItem::GetLabel() const
  135. {
  136.     return m_Label;
  137. }
  138. void    CMenuItem::SetLabel(const string& label)
  139. {
  140.     m_Label = label;
  141. }
  142.  
  143. const TCmdID&  CMenuItem::GetCommand()    const
  144. {
  145.     return m_CommandID;
  146. }
  147. void    CMenuItem::SetCommand(TCmdID cmd)
  148. {
  149.     m_CommandID = cmd;
  150. }
  151. bool            CMenuItem::HasImage()  const
  152. {
  153.     return m_ImageAlias.size() > 0;
  154. }
  155. const string&   CMenuItem::GetImageAlias() const
  156. {
  157.     return m_ImageAlias;
  158. }
  159. void    CMenuItem::SetImageAlias(const string& image_alias)
  160. {
  161.     m_ImageAlias = image_alias;
  162. }
  163. int  CMenuItem::GetState()  const
  164. {
  165.     return m_State;
  166. }
  167. void    CMenuItem::SetState(int state)  
  168. {
  169.     m_State = state;
  170. }
  171. bool    CMenuItem::IsEnabled() const
  172. {
  173.     return (m_State & eDisabled) == 0;
  174. }
  175. void    CMenuItem::Enable(bool b_en)
  176. {
  177.     x_SetState(eDisabled, ! b_en);
  178. }
  179. bool    CMenuItem::IsCheckType()   const
  180. {
  181.     return (m_State & eCheckItem) != 0;
  182. }
  183. bool    CMenuItem::IsChecked() const
  184. {
  185.     return (m_State & eCheckItem)  &&  m_State & eSet;
  186. }
  187. void    CMenuItem::SetCheck(bool b_set)
  188. {
  189.     x_SetState(eCheckItem | eRadioItem, eCheckItem);
  190.     x_SetState(eSet, b_set);
  191. }
  192. bool    CMenuItem::IsRadioType()   const
  193. {
  194.     return (m_State & eRadioItem) != 0;
  195. }
  196. bool    CMenuItem::IsRadioSelected() const
  197. {
  198.    return m_State & eRadioItem  &&  m_State & eSet;
  199. }
  200. void    CMenuItem::SelectRadio(bool b_set)
  201. {
  202.     x_SetState(eCheckItem | eRadioItem, eRadioItem);
  203.     x_SetState(eSet, b_set);
  204. }
  205. bool    CMenuItem::IsValid() const
  206. {
  207.     bool b_check = IsCheckType();
  208.     bool b_radio = IsRadioType();
  209.     
  210.     if(b_check  &&  b_radio)    {
  211.         return false; // cannot be both at the same time
  212.     } else if((b_check  ||  b_radio)  &&  ! IsItem())   {
  213.         return false;
  214.     } /*else if((m_State & eHideIfEmpty)  &&  ! IsSubmenu())  {
  215.         return false;
  216.     }*/ else if(! IsSeparator()  &&  m_Label.size()==0)   {
  217.         return false; // label must not be empty
  218.     }
  219.     return true;
  220. }
  221. /// Menu Item trees are merged based on item's labels. Labels specify unique path
  222. /// to an item (similarly to paths in file systems).
  223. void    CMenuItem::Merge(const CMenuItem& item)
  224. {
  225.     // this and "item" must be submenus with the same label
  226.     if(GetLabel() == item.GetLabel())   {
  227.           if(IsSubmenu()  &&  item.IsSubmenu())   {
  228.             // for every subitem in the given menu
  229.             for( TChildItem_CI it = item.SubItemsBegin(); it != item.SubItemsEnd(); it++ )   {
  230.                 const CMenuItem* sub_item = (*it)->GetValue();
  231.                 TChildItem_I it_target = FindSubItem(sub_item->GetLabel());
  232.             
  233.                 if(it_target != SubItemsEnd())   { // found potential target for merge
  234.                     CMenuItem* target_sub_item = (*it_target)->GetValue();
  235.                 
  236.                     if(target_sub_item->IsSubmenu())    { // submenu - merge recursively
  237.                         target_sub_item->Merge(*sub_item); 
  238.                     } else if(target_sub_item->IsItem()) { // command item
  239.                         string s_error;
  240.                         if(! sub_item->IsItem()) {
  241.                             s_error = ", because it is not a command item.";                                 
  242.                         } else if(target_sub_item->GetCommand() != sub_item->GetCommand())    {
  243.                             s_error = ", because they have different commands.";
  244.                         } 
  245.                         if(s_error.size())  {
  246.                             ERR_POST("CMenuItem::Merge() cannot merge item " 
  247.                                      << sub_item->GetLabel() 
  248.                                      << " into " << target_sub_item->GetLabel() 
  249.                                      << s_error);
  250.                         }
  251.                         // else, do nothing, because sub_item is identical to target_sub_item
  252.                     }
  253.                 } else { // sub_item is not found - add
  254.                     if(sub_item->GetType() != eSeparator)    {
  255.                         AddSubItem(sub_item->Clone());
  256.                     }
  257.                 }
  258.             } //for
  259.         } else {
  260.             ERR_POST("CMenuItem::Merge() cannot merge item " << item.GetLabel() 
  261.                      << " into " << GetLabel() << ", because they are not submenus.");
  262.         }
  263.     } else {
  264.         ERR_POST("CMenuItem::Merge() cannot merge item " << item.GetLabel() 
  265.                 << " into " << GetLabel() << ", because they have different labels.");     
  266.     }
  267. }
  268. CMenuItem*  CMenuItem::GetParent()
  269. {
  270.     TItemNode* parent_node = m_ItemNode.GetParent();
  271.     return parent_node ? parent_node->GetValue() : NULL;
  272. }
  273. const   CMenuItem*  CMenuItem::GetParent() const
  274. {
  275.     const TItemNode* parent_node = m_ItemNode.GetParent();
  276.     return parent_node ? parent_node->GetValue() : NULL;
  277. }
  278. CMenuItem*    CMenuItem::AddSubItem(CMenuItem* item)
  279. {
  280.     _ASSERT(IsSubmenu());
  281.     if(item)    {
  282.         TItemNode* node = & item->m_ItemNode;
  283.         m_ItemNode.AddNode(node);
  284.     } 
  285.     return item;
  286. }
  287. CMenuItem*  CMenuItem::AddSubItem()
  288. {
  289.     CMenuItem* item = new CMenuItem();
  290.     return AddSubItem(item);
  291. }
  292. CMenuItem*  CMenuItem::AddSubMenu(const string& label, const string& image_alias)
  293. {
  294.     CMenuItem* item = new CMenuItem(label, image_alias);
  295.     return AddSubItem(item);
  296. }
  297. CMenuItem*  CMenuItem::AddSubItem(const string& label, TCmdID cmd,  const string& image_alias, int state)
  298. {
  299.     CMenuItem* item = new CMenuItem(label, cmd, image_alias, state);
  300.     return AddSubItem(item);
  301. }
  302. bool    CMenuItem::IsSubmenuEmpty()
  303. {
  304.     return m_ItemNode.SubNodeBegin() == m_ItemNode.SubNodeEnd();
  305. }
  306. CMenuItem::TChildItem_I    CMenuItem::SubItemsBegin()
  307. {
  308.     return m_ItemNode.SubNodeBegin();
  309. }
  310. CMenuItem::TChildItem_I    CMenuItem::SubItemsEnd()
  311. {
  312.     return m_ItemNode.SubNodeEnd();
  313. }
  314. CMenuItem::TChildItem_CI    CMenuItem::SubItemsBegin()  const
  315. {
  316.     return m_ItemNode.SubNodeBegin();
  317. }
  318. CMenuItem::TChildItem_CI    CMenuItem::SubItemsEnd() const
  319. {
  320.     return m_ItemNode.SubNodeEnd();
  321. }
  322. CMenuItem*  CMenuItem::FindEqualSubItem(const CMenuItem& item)
  323. {
  324.     for(TChildItem_I it = SubItemsBegin(); it != SubItemsEnd(); ++it)  {
  325.         CMenuItem* curr = (*it)->GetValue();
  326.         if(curr->Equal(item))
  327.             return curr;
  328.     }
  329.     return NULL;
  330. }
  331. const CMenuItem*  CMenuItem::FindEqualSubItem(const CMenuItem& item) const
  332. {
  333.     for(TChildItem_CI it = SubItemsBegin(); it != SubItemsEnd(); ++it)  {
  334.         const CMenuItem* curr = (*it)->GetValue();
  335.         if(curr->Equal(item))
  336.             return curr;
  337.     }
  338.     return NULL;
  339. }
  340. CMenuItem::TChildItem_I    CMenuItem::FindSubItem(const CMenuItem& item)
  341. {
  342.     for(TChildItem_I it = SubItemsBegin(); it != SubItemsEnd(); ++it)  {
  343.         if((*it)->GetValue() == &item)
  344.             return it;
  345.     }
  346.     return SubItemsEnd();
  347. }
  348. CMenuItem::TChildItem_CI   CMenuItem::FindSubItem(const CMenuItem& item) const
  349. {
  350.     for(TChildItem_CI it = SubItemsBegin(); it != SubItemsEnd(); ++it)  {
  351.         if((*it)->GetValue() == &item)
  352.             return it;
  353.     }
  354.     return SubItemsEnd();
  355. }
  356. CMenuItem::TChildItem_I    CMenuItem::FindSubItem(const string& label)
  357. {
  358.     for(TChildItem_I it = SubItemsBegin(); it != SubItemsEnd(); ++it)  {
  359.         if((*it)->GetValue()->GetLabel() == label)
  360.             return it;
  361.     }
  362.     return SubItemsEnd();
  363. }
  364. CMenuItem::TChildItem_CI   CMenuItem::FindSubItem(const string& label) const
  365. {
  366.     for(TChildItem_CI it = SubItemsBegin(); it != SubItemsEnd(); ++it)  {
  367.         if((*it)->GetValue()->GetLabel() == label)
  368.             return it;
  369.     }
  370.     return SubItemsEnd();
  371. }
  372. ////////////////////////////////////////////////////////////////////////////////
  373. ///
  374. CMenuItem*  CreateMenuItems(const SMenuItemRec* items)
  375. {
  376.     if(items)   {
  377.         CMenuItem* root = NULL;
  378.         vector<CMenuItem*>  path;        
  379.         const SMenuItemRec* p_rec = items;        
  380.         while(p_rec)    {
  381.             CMenuItem* item = NULL;
  382.             if(p_rec->IsSubMenu())  {
  383.                 // create Submenu and add to path
  384.                 item = new CMenuItem(p_rec->m_Label, p_rec->m_ImageAlias);
  385.                 if(path.size()) {
  386.                     path.back()->AddSubItem(item);
  387.                 }   else {
  388.                     root = item;
  389.                 }
  390.                 path.push_back(item);
  391.             } else if(p_rec->IsSubMenuEnd())  {
  392.                 //end current submenu and eject it from path
  393.                 path.pop_back();
  394.                 if(path.empty())
  395.                     return root;
  396.             } else if(p_rec->m_Type == CMenuItem::eItem)    {
  397.                 // add command item
  398.                 item = new CMenuItem(p_rec->m_Label, p_rec->m_CommandID, 
  399.                                      p_rec->m_ImageAlias, p_rec->m_State);
  400.                 path.back()->AddSubItem(item);
  401.             } else if(p_rec->m_Type == CMenuItem::eSeparator)    {
  402.                 // add separator
  403.                 item = new CMenuItem();
  404.                 path.back()->AddSubItem(item);
  405.             }
  406.             p_rec++;
  407.         }        
  408.     }
  409.     return  NULL;        
  410. }
  411. END_NCBI_SCOPE
  412. /*
  413.  * ===========================================================================
  414.  * $Log: menu_item.cpp,v $
  415.  * Revision 1000.0  2004/06/01 21:29:16  gouriano
  416.  * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.6
  417.  *
  418.  * Revision 1.6  2004/05/21 22:27:53  gorelenk
  419.  * Added PCH ncbi_pch.hpp
  420.  *
  421.  * Revision 1.5  2004/05/13 17:30:37  yazhuk
  422.  * Removed eHideIfEmpty support
  423.  *
  424.  * Revision 1.4  2004/05/07 14:18:43  yazhuk
  425.  * Added Merge(), FindSubItem(string)
  426.  *
  427.  * Revision 1.3  2004/05/03 19:44:09  yazhuk
  428.  * Refactoring; fixed IsChecked()
  429.  *
  430.  * Revision 1.2  2004/04/28 19:28:29  tereshko
  431.  * Fixed test for a checked state of radio button
  432.  *
  433.  * Revision 1.1  2004/04/22 16:56:25  yazhuk
  434.  * Moved from menu.cpp, added support for images
  435.  *
  436.  * ===========================================================================
  437.  */