home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / common / menucmn.cpp < prev    next >
C/C++ Source or Header  |  2002-03-20  |  26KB  |  932 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        common/menucmn.cpp
  3. // Purpose:     wxMenu and wxMenuBar methods common to all ports
  4. // Author:      Vadim Zeitlin
  5. // Modified by:
  6. // Created:     26.10.99
  7. // RCS-ID:      $Id: menucmn.cpp,v 1.18 2002/03/18 19:41:26 VZ Exp $
  8. // Copyright:   (c) wxWindows team
  9. // Licence:     wxWindows license
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "menubase.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #if wxUSE_MENUS
  32.  
  33. #include <ctype.h>
  34.  
  35. #ifndef WX_PRECOMP
  36.     #include "wx/intl.h"
  37.     #include "wx/log.h"
  38.     #include "wx/menu.h"
  39. #endif
  40.  
  41. // ----------------------------------------------------------------------------
  42. // template lists
  43. // ----------------------------------------------------------------------------
  44.  
  45. #include "wx/listimpl.cpp"
  46.  
  47. WX_DEFINE_LIST(wxMenuList);
  48. WX_DEFINE_LIST(wxMenuItemList);
  49.  
  50. // ============================================================================
  51. // implementation
  52. // ============================================================================
  53.  
  54. // ----------------------------------------------------------------------------
  55. // wxMenuItem
  56. // ----------------------------------------------------------------------------
  57.  
  58. wxMenuItemBase::wxMenuItemBase(wxMenu *parentMenu,
  59.                                int id,
  60.                                const wxString& text,
  61.                                const wxString& help,
  62.                                wxItemKind kind,
  63.                                wxMenu *subMenu)
  64.               : m_text(text),
  65.                 m_help(help)
  66. {
  67.     wxASSERT_MSG( parentMenu != NULL, wxT("menuitem should have a menu") );
  68.  
  69.     m_parentMenu  = parentMenu;
  70.     m_subMenu     = subMenu;
  71.     m_isEnabled   = TRUE;
  72.     m_isChecked   = FALSE;
  73.     m_id          = id;
  74.     m_kind        = kind;
  75. }
  76.  
  77. wxMenuItemBase::~wxMenuItemBase()
  78. {
  79.     delete m_subMenu;
  80. }
  81.  
  82. #if wxUSE_ACCEL
  83.  
  84. // return wxAcceleratorEntry for the given menu string or NULL if none
  85. // specified
  86. wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
  87. {
  88.     // check for accelerators: they are given after '\t'
  89.     int posTab = label.Find(wxT('\t'));
  90.     if ( posTab != wxNOT_FOUND ) {
  91.         // parse the accelerator string
  92.         int keyCode = 0;
  93.         int accelFlags = wxACCEL_NORMAL;
  94.         wxString current;
  95.         for ( size_t n = (size_t)posTab + 1; n < label.Len(); n++ ) {
  96.             if ( (label[n] == '+') || (label[n] == '-') ) {
  97.                 if ( current == _("ctrl") )
  98.                     accelFlags |= wxACCEL_CTRL;
  99.                 else if ( current == _("alt") )
  100.                     accelFlags |= wxACCEL_ALT;
  101.                 else if ( current == _("shift") )
  102.                     accelFlags |= wxACCEL_SHIFT;
  103.                 else {
  104.                     // we may have "Ctrl-+", for example, but we still want to
  105.                     // catch typos like "Crtl-A" so only give the warning if we
  106.                     // have something before the current '+' or '-', else take
  107.                     // it as a literal symbol
  108.                     if ( current.empty() )
  109.                     {
  110.                         current += label[n];
  111.  
  112.                         // skip clearing it below
  113.                         continue;
  114.                     }
  115.                     else
  116.                     {
  117.                         wxLogDebug(wxT("Unknown accel modifier: '%s'"),
  118.                                    current.c_str());
  119.                     }
  120.                 }
  121.  
  122.                 current.clear();
  123.             }
  124.             else {
  125.                 current += wxTolower(label[n]);
  126.             }
  127.         }
  128.  
  129.         if ( current.IsEmpty() ) {
  130.             wxLogDebug(wxT("No accel key found, accel string ignored."));
  131.         }
  132.         else {
  133.             if ( current.Len() == 1 ) {
  134.                 // it's a letter
  135.                 keyCode = wxToupper(current[0U]);
  136.             }
  137.             else {
  138.                 // is it a function key?
  139.                 if ( current[0U] == 'f' && isdigit(current[1U]) &&
  140.                      (current.Len() == 2 ||
  141.                      (current.Len() == 3 && isdigit(current[2U]))) ) {
  142.                     int n;
  143.                     wxSscanf(current.c_str() + 1, wxT("%d"), &n);
  144.  
  145.                     keyCode = WXK_F1 + n - 1;
  146.                 }
  147.                 else {
  148.                     // several special cases
  149.                     current.MakeUpper();
  150.                     if ( current == wxT("DEL") ) {
  151.                         keyCode = WXK_DELETE;
  152.                     }
  153.                     else if ( current == wxT("DELETE") ) {
  154.                         keyCode = WXK_DELETE;
  155.                     }
  156.                     else if ( current == wxT("INS") ) {
  157.                         keyCode = WXK_INSERT;
  158.                     }
  159.                     else if ( current == wxT("INSERT") ) {
  160.                         keyCode = WXK_INSERT;
  161.                     }
  162. #if 0
  163.                     else if ( current == wxT("PGUP") ) {
  164.                         keyCode = VK_PRIOR;
  165.                     }
  166.                     else if ( current == wxT("PGDN") ) {
  167.                         keyCode = VK_NEXT;
  168.                     }
  169. #endif
  170.                     else
  171.                     {
  172.                         wxLogDebug(wxT("Unrecognized accel key '%s', accel string ignored."),
  173.                                    current.c_str());
  174.                     }
  175.                 }
  176.             }
  177.         }
  178.  
  179.         if ( keyCode ) {
  180.             // we do have something
  181.             return new wxAcceleratorEntry(accelFlags, keyCode);
  182.         }
  183.     }
  184.  
  185.     return (wxAcceleratorEntry *)NULL;
  186. }
  187.  
  188. wxAcceleratorEntry *wxMenuItemBase::GetAccel() const
  189. {
  190.     return wxGetAccelFromString(GetText());
  191. }
  192.  
  193. void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
  194. {
  195.     wxString text = m_text.BeforeFirst(wxT('\t'));
  196.     if ( accel )
  197.     {
  198.         text += wxT('\t');
  199.  
  200.         int flags = accel->GetFlags();
  201.         if ( flags & wxACCEL_ALT )
  202.             text += wxT("Alt-");
  203.         if ( flags & wxACCEL_CTRL )
  204.             text += wxT("Ctrl-");
  205.         if ( flags & wxACCEL_SHIFT )
  206.             text += wxT("Shift-");
  207.  
  208.         int code = accel->GetKeyCode();
  209.         switch ( code )
  210.         {
  211.             case WXK_F1:
  212.             case WXK_F2:
  213.             case WXK_F3:
  214.             case WXK_F4:
  215.             case WXK_F5:
  216.             case WXK_F6:
  217.             case WXK_F7:
  218.             case WXK_F8:
  219.             case WXK_F9:
  220.             case WXK_F10:
  221.             case WXK_F11:
  222.             case WXK_F12:
  223.                 text << wxT('F') << code - WXK_F1 + 1;
  224.                 break;
  225.  
  226.             // if there are any other keys wxGetAccelFromString() may return,
  227.             // we should process them here
  228.  
  229.             default:
  230.                 if ( wxIsalnum(code) )
  231.                 {
  232.                     text << (wxChar)code;
  233.  
  234.                     break;
  235.                 }
  236.  
  237.                 wxFAIL_MSG( wxT("unknown keyboard accel") );
  238.         }
  239.     }
  240.  
  241.     SetText(text);
  242. }
  243.  
  244. #endif // wxUSE_ACCEL
  245.  
  246. // ----------------------------------------------------------------------------
  247. // wxMenu ctor and dtor
  248. // ----------------------------------------------------------------------------
  249.  
  250. void wxMenuBase::Init(long style)
  251. {
  252.     m_items.DeleteContents(TRUE);
  253.  
  254.     m_menuBar = (wxMenuBar *)NULL;
  255.     m_menuParent = (wxMenu *)NULL;
  256.  
  257.     m_invokingWindow = (wxWindow *)NULL;
  258.     m_style = style;
  259.     m_clientData = (void *)NULL;
  260.     m_eventHandler = this;
  261.  
  262. #if wxUSE_MENU_CALLBACK
  263.     m_callback = (wxFunction) NULL;
  264. #endif // wxUSE_MENU_CALLBACK
  265. }
  266.  
  267. wxMenuBase::~wxMenuBase()
  268. {
  269.     // nothing to do, wxMenuItemList dtor will delete the menu items.
  270.  
  271.     // Actually, in GTK, the submenus have to get deleted first.
  272. }
  273.  
  274. // ----------------------------------------------------------------------------
  275. // wxMenu item adding/removing
  276. // ----------------------------------------------------------------------------
  277.  
  278. void wxMenuBase::AddSubMenu(wxMenu *submenu)
  279. {
  280.     wxCHECK_RET( submenu, _T("can't add a NULL submenu") );
  281.  
  282.     if ( m_menuBar )
  283.     {
  284.         submenu->Attach(m_menuBar);
  285.     }
  286.  
  287.     submenu->SetParent((wxMenu *)this);
  288. }
  289.  
  290. bool wxMenuBase::DoAppend(wxMenuItem *item)
  291. {
  292.     wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Append()") );
  293.  
  294.     m_items.Append(item);
  295.     if ( item->IsSubMenu() )
  296.     {
  297.         AddSubMenu(item->GetSubMenu());
  298.     }
  299.  
  300.     return TRUE;
  301. }
  302.  
  303. bool wxMenuBase::Insert(size_t pos, wxMenuItem *item)
  304. {
  305.     wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Insert") );
  306.  
  307.     if ( pos == GetMenuItemCount() )
  308.     {
  309.         return DoAppend(item);
  310.     }
  311.     else
  312.     {
  313.         wxCHECK_MSG( pos < GetMenuItemCount(), FALSE,
  314.                      wxT("invalid index in wxMenu::Insert") );
  315.  
  316.         return DoInsert(pos, item);
  317.     }
  318. }
  319.  
  320. bool wxMenuBase::DoInsert(size_t pos, wxMenuItem *item)
  321. {
  322.     wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Insert()") );
  323.  
  324.     wxMenuItemList::Node *node = m_items.Item(pos);
  325.     wxCHECK_MSG( node, FALSE, wxT("invalid index in wxMenu::Insert()") );
  326.  
  327.     m_items.Insert(node, item);
  328.     if ( item->IsSubMenu() )
  329.     {
  330.         AddSubMenu(item->GetSubMenu());
  331.     }
  332.  
  333.     return TRUE;
  334. }
  335.  
  336. wxMenuItem *wxMenuBase::Remove(wxMenuItem *item)
  337. {
  338.     wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Remove") );
  339.  
  340.     return DoRemove(item);
  341. }
  342.  
  343. wxMenuItem *wxMenuBase::DoRemove(wxMenuItem *item)
  344. {
  345.     wxMenuItemList::Node *node = m_items.Find(item);
  346.  
  347.     // if we get here, the item is valid or one of Remove() functions is broken
  348.     wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
  349.  
  350.     // we detach the item, but we do delete the list node (i.e. don't call
  351.     // DetachNode() here!)
  352.     node->SetData((wxMenuItem *)NULL);  // to prevent it from deleting the item
  353.     m_items.DeleteNode(node);
  354.  
  355.     // item isn't attached to anything any more
  356.     wxMenu *submenu = item->GetSubMenu();
  357.     if ( submenu )
  358.     {
  359.         submenu->SetParent((wxMenu *)NULL);
  360.     }
  361.  
  362.     return item;
  363. }
  364.  
  365. bool wxMenuBase::Delete(wxMenuItem *item)
  366. {
  367.     wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Delete") );
  368.  
  369.     return DoDelete(item);
  370. }
  371.  
  372. bool wxMenuBase::DoDelete(wxMenuItem *item)
  373. {
  374.     wxMenuItem *item2 = DoRemove(item);
  375.     wxCHECK_MSG( item2, FALSE, wxT("failed to delete menu item") );
  376.  
  377.     // don't delete the submenu
  378.     item2->SetSubMenu((wxMenu *)NULL);
  379.  
  380.     delete item2;
  381.  
  382.     return TRUE;
  383. }
  384.  
  385. bool wxMenuBase::Destroy(wxMenuItem *item)
  386. {
  387.     wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Destroy") );
  388.  
  389.     return DoDestroy(item);
  390. }
  391.  
  392. bool wxMenuBase::DoDestroy(wxMenuItem *item)
  393. {
  394.     wxMenuItem *item2 = DoRemove(item);
  395.     wxCHECK_MSG( item2, FALSE, wxT("failed to delete menu item") );
  396.  
  397.     delete item2;
  398.  
  399.     return TRUE;
  400. }
  401.  
  402. // ----------------------------------------------------------------------------
  403. // wxMenu searching for items
  404. // ----------------------------------------------------------------------------
  405.  
  406. // Finds the item id matching the given string, -1 if not found.
  407. int wxMenuBase::FindItem(const wxString& text) const
  408. {
  409.     wxString label = wxMenuItem::GetLabelFromText(text);
  410.     for ( wxMenuItemList::Node *node = m_items.GetFirst();
  411.           node;
  412.           node = node->GetNext() )
  413.     {
  414.         wxMenuItem *item = node->GetData();
  415.         if ( item->IsSubMenu() )
  416.         {
  417.             int rc = item->GetSubMenu()->FindItem(label);
  418.             if ( rc != wxNOT_FOUND )
  419.                 return rc;
  420.         }
  421.  
  422.         // we execute this code for submenus as well to alllow finding them by
  423.         // name just like the ordinary items
  424.         if ( !item->IsSeparator() )
  425.         {
  426.             if ( item->GetLabel() == label )
  427.                 return item->GetId();
  428.         }
  429.     }
  430.  
  431.     return wxNOT_FOUND;
  432. }
  433.  
  434. // recursive search for item by id
  435. wxMenuItem *wxMenuBase::FindItem(int itemId, wxMenu **itemMenu) const
  436. {
  437.     if ( itemMenu )
  438.         *itemMenu = NULL;
  439.  
  440.     wxMenuItem *item = NULL;
  441.     for ( wxMenuItemList::Node *node = m_items.GetFirst();
  442.           node && !item;
  443.           node = node->GetNext() )
  444.     {
  445.         item = node->GetData();
  446.  
  447.         if ( item->GetId() == itemId )
  448.         {
  449.             if ( itemMenu )
  450.                 *itemMenu = (wxMenu *)this;
  451.         }
  452.         else if ( item->IsSubMenu() )
  453.         {
  454.             item = item->GetSubMenu()->FindItem(itemId, itemMenu);
  455.         }
  456.         else
  457.         {
  458.             // don't exit the loop
  459.             item = NULL;
  460.         }
  461.     }
  462.  
  463.     return item;
  464. }
  465.  
  466. // non recursive search
  467. wxMenuItem *wxMenuBase::FindChildItem(int id, size_t *ppos) const
  468. {
  469.     wxMenuItem *item = (wxMenuItem *)NULL;
  470.     wxMenuItemList::Node *node = GetMenuItems().GetFirst();
  471.  
  472.     size_t pos;
  473.     for ( pos = 0; node; pos++ )
  474.     {
  475.         if ( node->GetData()->GetId() == id )
  476.         {
  477.             item = node->GetData();
  478.  
  479.             break;
  480.         }
  481.  
  482.         node = node->GetNext();
  483.     }
  484.  
  485.     if ( ppos )
  486.     {
  487.         *ppos = item ? pos : (size_t)wxNOT_FOUND;
  488.     }
  489.  
  490.     return item;
  491. }
  492.  
  493. // ----------------------------------------------------------------------------
  494. // wxMenu helpers used by derived classes
  495. // ----------------------------------------------------------------------------
  496.  
  497. // Update a menu and all submenus recursively. source is the object that has
  498. // the update event handlers defined for it. If NULL, the menu or associated
  499. // window will be used.
  500. void wxMenuBase::UpdateUI(wxEvtHandler* source)
  501. {
  502.     if ( !source && GetInvokingWindow() )
  503.         source = GetInvokingWindow()->GetEventHandler();
  504.     if ( !source )
  505.         source = GetEventHandler();
  506.     if ( !source )
  507.         source = this;
  508.  
  509.     wxMenuItemList::Node* node = GetMenuItems().GetFirst();
  510.     while ( node )
  511.     {
  512.         wxMenuItem* item = node->GetData();
  513.         if ( !item->IsSeparator() )
  514.         {
  515.             wxWindowID id = item->GetId();
  516.             wxUpdateUIEvent event(id);
  517.             event.SetEventObject( source );
  518.  
  519.             if ( source->ProcessEvent(event) )
  520.             {
  521.                 // if anything changed, update the chanegd attribute
  522.                 if (event.GetSetText())
  523.                     SetLabel(id, event.GetText());
  524.                 if (event.GetSetChecked())
  525.                     Check(id, event.GetChecked());
  526.                 if (event.GetSetEnabled())
  527.                     Enable(id, event.GetEnabled());
  528.             }
  529.  
  530.             // recurse to the submenus
  531.             if ( item->GetSubMenu() )
  532.                 item->GetSubMenu()->UpdateUI(source);
  533.         }
  534.         //else: item is a separator (which don't process update UI events)
  535.  
  536.         node = node->GetNext();
  537.     }
  538. }
  539.  
  540. bool wxMenuBase::SendEvent(int id, int checked)
  541. {
  542.     wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
  543.     event.SetEventObject(this);
  544.     event.SetInt(checked);
  545.  
  546.     bool processed = FALSE;
  547.  
  548. #if wxUSE_MENU_CALLBACK
  549.     // Try a callback
  550.     if (m_callback)
  551.     {
  552.         (void)(*(m_callback))(*this, event);
  553.         processed = TRUE;
  554.     }
  555. #endif // wxUSE_MENU_CALLBACK
  556.  
  557.     // Try the menu's event handler
  558.     if ( !processed )
  559.     {
  560.         wxEvtHandler *handler = GetEventHandler();
  561.         if ( handler )
  562.             processed = handler->ProcessEvent(event);
  563.     }
  564.  
  565.     // Try the window the menu was popped up from (and up through the
  566.     // hierarchy)
  567.     if ( !processed )
  568.     {
  569.         const wxMenuBase *menu = this;
  570.         while ( menu )
  571.         {
  572.             wxWindow *win = menu->GetInvokingWindow();
  573.             if ( win )
  574.             {
  575.                 processed = win->GetEventHandler()->ProcessEvent(event);
  576.                 break;
  577.             }
  578.  
  579.             menu = menu->GetParent();
  580.         }
  581.     }
  582.  
  583.     return processed;
  584. }
  585.  
  586. // ----------------------------------------------------------------------------
  587. // wxMenu attaching/detaching to/from menu bar
  588. // ----------------------------------------------------------------------------
  589.  
  590. void wxMenuBase::Attach(wxMenuBarBase *menubar)
  591. {
  592.     // use Detach() instead!
  593.     wxASSERT_MSG( menubar, _T("menu can't be attached to NULL menubar") );
  594.  
  595.     // use IsAttached() to prevent this from happening
  596.     wxASSERT_MSG( !m_menuBar, _T("attaching menu twice?") );
  597.  
  598.     m_menuBar = (wxMenuBar *)menubar;
  599. }
  600.  
  601. void wxMenuBase::Detach()
  602. {
  603.     // use IsAttached() to prevent this from happening
  604.     wxASSERT_MSG( m_menuBar, _T("detaching unattached menu?") );
  605.  
  606.     m_menuBar = NULL;
  607. }
  608.  
  609. // ----------------------------------------------------------------------------
  610. // wxMenu functions forwarded to wxMenuItem
  611. // ----------------------------------------------------------------------------
  612.  
  613. void wxMenuBase::Enable( int id, bool enable )
  614. {
  615.     wxMenuItem *item = FindItem(id);
  616.  
  617.     wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
  618.  
  619.     item->Enable(enable);
  620. }
  621.  
  622. bool wxMenuBase::IsEnabled( int id ) const
  623. {
  624.     wxMenuItem *item = FindItem(id);
  625.  
  626.     wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsEnabled: no such item") );
  627.  
  628.     return item->IsEnabled();
  629. }
  630.  
  631. void wxMenuBase::Check( int id, bool enable )
  632. {
  633.     wxMenuItem *item = FindItem(id);
  634.  
  635.     wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
  636.  
  637.     item->Check(enable);
  638. }
  639.  
  640. bool wxMenuBase::IsChecked( int id ) const
  641. {
  642.     wxMenuItem *item = FindItem(id);
  643.  
  644.     wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsChecked: no such item") );
  645.  
  646.     return item->IsChecked();
  647. }
  648.  
  649. void wxMenuBase::SetLabel( int id, const wxString &label )
  650. {
  651.     wxMenuItem *item = FindItem(id);
  652.  
  653.     wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
  654.  
  655.     item->SetText(label);
  656. }
  657.  
  658. wxString wxMenuBase::GetLabel( int id ) const
  659. {
  660.     wxMenuItem *item = FindItem(id);
  661.  
  662.     wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetLabel: no such item") );
  663.  
  664.     return item->GetText();
  665. }
  666.  
  667. void wxMenuBase::SetHelpString( int id, const wxString& helpString )
  668. {
  669.     wxMenuItem *item = FindItem(id);
  670.  
  671.     wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
  672.  
  673.     item->SetHelp( helpString );
  674. }
  675.  
  676. wxString wxMenuBase::GetHelpString( int id ) const
  677. {
  678.     wxMenuItem *item = FindItem(id);
  679.  
  680.     wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetHelpString: no such item") );
  681.  
  682.     return item->GetHelp();
  683. }
  684.  
  685. // ----------------------------------------------------------------------------
  686. // wxMenuBarBase ctor and dtor
  687. // ----------------------------------------------------------------------------
  688.  
  689. wxMenuBarBase::wxMenuBarBase()
  690. {
  691.     // we own the menus when we get them
  692.     m_menus.DeleteContents(TRUE);
  693.  
  694.     // not attached yet
  695.     m_menuBarFrame = NULL;
  696. }
  697.  
  698. wxMenuBarBase::~wxMenuBarBase()
  699. {
  700.     // nothing to do, the list will delete the menus because of the call to
  701.     // DeleteContents() above
  702. }
  703.  
  704. // ----------------------------------------------------------------------------
  705. // wxMenuBar item access: the base class versions manage m_menus list, the
  706. // derived class should reflect the changes in the real menubar
  707. // ----------------------------------------------------------------------------
  708.  
  709. wxMenu *wxMenuBarBase::GetMenu(size_t pos) const
  710. {
  711.     wxMenuList::Node *node = m_menus.Item(pos);
  712.     wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::GetMenu()") );
  713.  
  714.     return node->GetData();
  715. }
  716.  
  717. bool wxMenuBarBase::Append(wxMenu *menu, const wxString& WXUNUSED(title))
  718. {
  719.     wxCHECK_MSG( menu, FALSE, wxT("can't append NULL menu") );
  720.  
  721.     m_menus.Append(menu);
  722.     menu->Attach(this);
  723.  
  724.     return TRUE;
  725. }
  726.  
  727. bool wxMenuBarBase::Insert(size_t pos, wxMenu *menu,
  728.                            const wxString& title)
  729. {
  730.     if ( pos == m_menus.GetCount() )
  731.     {
  732.         return wxMenuBarBase::Append(menu, title);
  733.     }
  734.     else // not at the end
  735.     {
  736.         wxCHECK_MSG( menu, FALSE, wxT("can't insert NULL menu") );
  737.  
  738.         wxMenuList::Node *node = m_menus.Item(pos);
  739.         wxCHECK_MSG( node, FALSE, wxT("bad index in wxMenuBar::Insert()") );
  740.  
  741.         m_menus.Insert(node, menu);
  742.         menu->Attach(this);
  743.  
  744.         return TRUE;
  745.     }
  746. }
  747.  
  748. wxMenu *wxMenuBarBase::Replace(size_t pos, wxMenu *menu,
  749.                                const wxString& WXUNUSED(title))
  750. {
  751.     wxCHECK_MSG( menu, NULL, wxT("can't insert NULL menu") );
  752.  
  753.     wxMenuList::Node *node = m_menus.Item(pos);
  754.     wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Replace()") );
  755.  
  756.     wxMenu *menuOld = node->GetData();
  757.     node->SetData(menu);
  758.  
  759.     menu->Attach(this);
  760.     menuOld->Detach();
  761.  
  762.     return menuOld;
  763. }
  764.  
  765. wxMenu *wxMenuBarBase::Remove(size_t pos)
  766. {
  767.     wxMenuList::Node *node = m_menus.Item(pos);
  768.     wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Remove()") );
  769.  
  770.     node = m_menus.DetachNode(node);
  771.     wxCHECK( node, NULL );  // unexpected
  772.     wxMenu *menu = node->GetData();
  773.     menu->Detach();
  774.  
  775.     delete node;
  776.  
  777.     return menu;
  778. }
  779.  
  780. int wxMenuBarBase::FindMenu(const wxString& title) const
  781. {
  782.     wxString label = wxMenuItem::GetLabelFromText(title);
  783.  
  784.     size_t count = GetMenuCount();
  785.     for ( size_t i = 0; i < count; i++ )
  786.     {
  787.         wxString title2 = GetLabelTop(i);
  788.         if ( (title2 == title) ||
  789.              (wxMenuItem::GetLabelFromText(title2) == label) )
  790.         {
  791.             // found
  792.             return (int)i; 
  793.         }
  794.     }
  795.  
  796.     return wxNOT_FOUND;
  797.  
  798. }
  799.  
  800. // ----------------------------------------------------------------------------
  801. // wxMenuBar attaching/detaching to/from the frame
  802. // ----------------------------------------------------------------------------
  803.  
  804. void wxMenuBarBase::Attach(wxFrame *frame)
  805. {
  806.     wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
  807.  
  808.     m_menuBarFrame = frame;
  809. }
  810.  
  811. void wxMenuBarBase::Detach()
  812. {
  813.     wxASSERT_MSG( IsAttached(), wxT("detaching unattached menubar") );
  814.  
  815.     m_menuBarFrame = NULL;
  816. }
  817.  
  818. // ----------------------------------------------------------------------------
  819. // wxMenuBar searching for items
  820. // ----------------------------------------------------------------------------
  821.  
  822. wxMenuItem *wxMenuBarBase::FindItem(int id, wxMenu **menu) const
  823. {
  824.     if ( menu )
  825.         *menu = NULL;
  826.  
  827.     wxMenuItem *item = NULL;
  828.     size_t count = GetMenuCount();
  829.     for ( size_t i = 0; !item && (i < count); i++ )
  830.     {
  831.         item = m_menus[i]->FindItem(id, menu);
  832.     }
  833.  
  834.     return item;
  835. }
  836.  
  837. int wxMenuBarBase::FindMenuItem(const wxString& menu, const wxString& item) const
  838. {
  839.     wxString label = wxMenuItem::GetLabelFromText(menu);
  840.  
  841.     int i = 0;
  842.     wxMenuList::Node *node;
  843.     for ( node = m_menus.GetFirst(); node; node = node->GetNext(), i++ )
  844.     {
  845.         if ( label == wxMenuItem::GetLabelFromText(GetLabelTop(i)) )
  846.             return node->GetData()->FindItem(item);
  847.     }
  848.  
  849.     return wxNOT_FOUND;
  850. }
  851.  
  852. // ---------------------------------------------------------------------------
  853. // wxMenuBar functions forwarded to wxMenuItem
  854. // ---------------------------------------------------------------------------
  855.  
  856. void wxMenuBarBase::Enable(int id, bool enable)
  857. {
  858.     wxMenuItem *item = FindItem(id);
  859.  
  860.     wxCHECK_RET( item, wxT("attempt to enable an item which doesn't exist") );
  861.  
  862.     item->Enable(enable);
  863. }
  864.  
  865. void wxMenuBarBase::Check(int id, bool check)
  866. {
  867.     wxMenuItem *item = FindItem(id);
  868.  
  869.     wxCHECK_RET( item, wxT("attempt to check an item which doesn't exist") );
  870.     wxCHECK_RET( item->IsCheckable(), wxT("attempt to check an uncheckable item") );
  871.  
  872.     item->Check(check);
  873. }
  874.  
  875. bool wxMenuBarBase::IsChecked(int id) const
  876. {
  877.     wxMenuItem *item = FindItem(id);
  878.  
  879.     wxCHECK_MSG( item, FALSE, wxT("wxMenuBar::IsChecked(): no such item") );
  880.  
  881.     return item->IsChecked();
  882. }
  883.  
  884. bool wxMenuBarBase::IsEnabled(int id) const
  885. {
  886.     wxMenuItem *item = FindItem(id);
  887.  
  888.     wxCHECK_MSG( item, FALSE, wxT("wxMenuBar::IsEnabled(): no such item") );
  889.  
  890.     return item->IsEnabled();
  891. }
  892.  
  893. void wxMenuBarBase::SetLabel(int id, const wxString& label)
  894. {
  895.     wxMenuItem *item = FindItem(id);
  896.  
  897.     wxCHECK_RET( item, wxT("wxMenuBar::SetLabel(): no such item") );
  898.  
  899.     item->SetText(label);
  900. }
  901.  
  902. wxString wxMenuBarBase::GetLabel(int id) const
  903. {
  904.     wxMenuItem *item = FindItem(id);
  905.  
  906.     wxCHECK_MSG( item, wxEmptyString,
  907.                  wxT("wxMenuBar::GetLabel(): no such item") );
  908.  
  909.     return item->GetText();
  910. }
  911.  
  912. void wxMenuBarBase::SetHelpString(int id, const wxString& helpString)
  913. {
  914.     wxMenuItem *item = FindItem(id);
  915.  
  916.     wxCHECK_RET( item, wxT("wxMenuBar::SetHelpString(): no such item") );
  917.  
  918.     item->SetHelp(helpString);
  919. }
  920.  
  921. wxString wxMenuBarBase::GetHelpString(int id) const
  922. {
  923.     wxMenuItem *item = FindItem(id);
  924.  
  925.     wxCHECK_MSG( item, wxEmptyString,
  926.                  wxT("wxMenuBar::GetHelpString(): no such item") );
  927.  
  928.     return item->GetHelp();
  929. }
  930.  
  931. #endif // wxUSE_MENUS
  932.