new wxMenu stuff and thread implementations
[wxWidgets.git] / src / os2 / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: menu.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/10/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/frame.h"
17 #include "wx/menu.h"
18 #include "wx/utils.h"
19 #include "wx/intl.h"
20 #include "wx/log.h"
21 #endif
22
23 #if wxUSE_OWNER_DRAWN
24 #include "wx/ownerdrw.h"
25 #endif
26
27 #include "wx/os2/private.h"
28
29 // other standard headers
30 #include <string.h>
31
32 // ----------------------------------------------------------------------------
33 // global variables
34 // ----------------------------------------------------------------------------
35
36 extern wxMenu *wxCurrentPopupMenu;
37
38 // ----------------------------------------------------------------------------
39 // constants
40 // ----------------------------------------------------------------------------
41
42 // the (popup) menu title has this special id
43 static const int idMenuTitle = -2;
44
45 // ----------------------------------------------------------------------------
46 // macros
47 // ----------------------------------------------------------------------------
48
49 #if !USE_SHARED_LIBRARY
50 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
51 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
52 #endif
53
54 // ============================================================================
55 // implementation
56 // ============================================================================
57
58 // ---------------------------------------------------------------------------
59 // wxMenu construction, adding and removing menu items
60 // ---------------------------------------------------------------------------
61
62 // Construct a menu with optional title (then use append)
63 void wxMenu::Init()
64 {
65 m_doBreak = FALSE;
66
67 // create the menu
68 m_hMenu = (WXHMENU)0; // CreatePopupMenu();
69 if ( !m_hMenu )
70 {
71 wxLogLastError("CreatePopupMenu");
72 }
73
74 // if we have a title, insert it in the beginning of the menu
75 if ( !!m_title )
76 {
77 Append(idMenuTitle, m_title);
78 AppendSeparator();
79 }
80 }
81
82 // The wxWindow destructor will take care of deleting the submenus.
83 wxMenu::~wxMenu()
84 {
85 // we should free Windows resources only if Windows doesn't do it for us
86 // which happens if we're attached to a menubar or a submenu of another
87 // menu
88 if ( !IsAttached() && !GetParent() )
89 {
90 /*
91 if ( !::DestroyMenu(GetHmenu()) )
92 {
93 wxLogLastError("DestroyMenu");
94 }
95 */
96 }
97
98 #if wxUSE_ACCEL
99 // delete accels
100 WX_CLEAR_ARRAY(m_accels);
101 #endif // wxUSE_ACCEL
102 }
103
104 void wxMenu::Break()
105 {
106 // this will take effect during the next call to Append()
107 m_doBreak = TRUE;
108 }
109
110 #if wxUSE_ACCEL
111
112 int wxMenu::FindAccel(int id) const
113 {
114 size_t n, count = m_accels.GetCount();
115 for ( n = 0; n < count; n++ )
116 {
117 if ( m_accels[n]->m_command == id )
118 return n;
119 }
120
121 return wxNOT_FOUND;
122 }
123
124 void wxMenu::UpdateAccel(wxMenuItem *item)
125 {
126 // find the (new) accel for this item
127 wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
128 if ( accel )
129 accel->m_command = item->GetId();
130
131 // find the old one
132 int n = FindAccel(item->GetId());
133 if ( n == wxNOT_FOUND )
134 {
135 // no old, add new if any
136 if ( accel )
137 m_accels.Add(accel);
138 else
139 return; // skipping RebuildAccelTable() below
140 }
141 else
142 {
143 // replace old with new or just remove the old one if no new
144 delete m_accels[n];
145 if ( accel )
146 m_accels[n] = accel;
147 else
148 m_accels.Remove(n);
149 }
150
151 if ( IsAttached() )
152 {
153 m_menuBar->RebuildAccelTable();
154 }
155 }
156
157 #endif // wxUSE_ACCEL
158
159 // append a new item or submenu to the menu
160 bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
161 {
162 #if wxUSE_ACCEL
163 UpdateAccel(pItem);
164 #endif // wxUSE_ACCEL
165
166 UINT flags = 0;
167 // TODO:
168 /*
169 // if "Break" has just been called, insert a menu break before this item
170 // (and don't forget to reset the flag)
171 if ( m_doBreak ) {
172 flags |= MF_MENUBREAK;
173 m_doBreak = FALSE;
174 }
175
176 if ( pItem->IsSeparator() ) {
177 flags |= MF_SEPARATOR;
178 }
179
180 // id is the numeric id for normal menu items and HMENU for submenus as
181 // required by ::AppendMenu() API
182 UINT id;
183 wxMenu *submenu = pItem->GetSubMenu();
184 if ( submenu != NULL ) {
185 wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );
186
187 submenu->SetParent(this);
188
189 id = (UINT)submenu->GetHMenu();
190
191 flags |= MF_POPUP;
192 }
193 else {
194 id = pItem->GetId();
195 }
196
197 LPCTSTR pData;
198
199 #if wxUSE_OWNER_DRAWN
200 if ( pItem->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
201 // item draws itself, pass pointer to it in data parameter
202 flags |= MF_OWNERDRAW;
203 pData = (LPCTSTR)pItem;
204 }
205 else
206 #endif
207 {
208 // menu is just a normal string (passed in data parameter)
209 flags |= MF_STRING;
210
211 pData = (char*)pItem->GetText().c_str();
212 }
213
214 BOOL ok;
215 if ( pos == (size_t)-1 )
216 {
217 ok = ::AppendMenu(GetHmenu(), flags, id, pData);
218 }
219 else
220 {
221 ok = ::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData);
222 }
223
224 if ( !ok )
225 {
226 wxLogLastError("Insert or AppendMenu");
227
228 return FALSE;
229 }
230 else
231 {
232 // if we just appended the title, highlight it
233 #ifdef __WIN32__
234 if ( (int)id == idMenuTitle )
235 {
236 // visually select the menu title
237 MENUITEMINFO mii;
238 mii.cbSize = sizeof(mii);
239 mii.fMask = MIIM_STATE;
240 mii.fState = MFS_DEFAULT;
241
242 if ( !SetMenuItemInfo(GetHmenu(), (unsigned)id, FALSE, &mii) )
243 {
244 wxLogLastError(wxT("SetMenuItemInfo"));
245 }
246 }
247 #endif // __WIN32__
248
249 // if we're already attached to the menubar, we must update it
250 if ( IsAttached() )
251 {
252 m_menuBar->Refresh();
253 }
254
255 return TRUE;
256 }
257 */
258 return FALSE;
259 }
260
261 bool wxMenu::DoAppend(wxMenuItem *item)
262 {
263 return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
264 }
265
266 bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
267 {
268 return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
269 }
270
271 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
272 {
273 // we need to find the items position in the child list
274 size_t pos;
275 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
276 for ( pos = 0; node; pos++ )
277 {
278 if ( node->GetData() == item )
279 break;
280
281 node = node->GetNext();
282 }
283
284 // DoRemove() (unlike Remove) can only be called for existing item!
285 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
286
287 #if wxUSE_ACCEL
288 // remove the corresponding accel from the accel table
289 int n = FindAccel(item->GetId());
290 if ( n != wxNOT_FOUND )
291 {
292 delete m_accels[n];
293
294 m_accels.Remove(n);
295 }
296 //else: this item doesn't have an accel, nothing to do
297 #endif // wxUSE_ACCEL
298 /*
299 // remove the item from the menu
300 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
301 {
302 wxLogLastError("RemoveMenu");
303 }
304 */
305 if ( IsAttached() )
306 {
307 // otherwise, the chane won't be visible
308 m_menuBar->Refresh();
309 }
310
311 // and from internal data structures
312 return wxMenuBase::DoRemove(item);
313 }
314
315 // ---------------------------------------------------------------------------
316 // accelerator helpers
317 // ---------------------------------------------------------------------------
318
319 #if wxUSE_ACCEL
320
321 // create the wxAcceleratorEntries for our accels and put them into provided
322 // array - return the number of accels we have
323 size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
324 {
325 size_t count = GetAccelCount();
326 for ( size_t n = 0; n < count; n++ )
327 {
328 *accels++ = *m_accels[n];
329 }
330
331 return count;
332 }
333
334 #endif // wxUSE_ACCEL
335
336 // ---------------------------------------------------------------------------
337 // set wxMenu title
338 // ---------------------------------------------------------------------------
339
340 void wxMenu::SetTitle(const wxString& label)
341 {
342 bool hasNoTitle = m_title.IsEmpty();
343 m_title = label;
344
345 HMENU hMenu = GetHmenu();
346
347 if ( hasNoTitle )
348 {
349 if ( !label.IsEmpty() )
350 {
351 /*
352 if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
353 (unsigned)idMenuTitle, m_title) ||
354 !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
355 {
356 wxLogLastError("InsertMenu");
357 }
358 */
359 }
360 }
361 else
362 {
363 if ( label.IsEmpty() )
364 {
365 /*
366 // remove the title and the separator after it
367 if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) ||
368 !RemoveMenu(hMenu, 0, MF_BYPOSITION) )
369 {
370 wxLogLastError("RemoveMenu");
371 }
372 */
373 }
374 else
375 {
376 /*
377 // modify the title
378 if ( !ModifyMenu(hMenu, 0u,
379 MF_BYPOSITION | MF_STRING,
380 (unsigned)idMenuTitle, m_title) )
381 {
382 wxLogLastError("ModifyMenu");
383 }
384 */
385 }
386 }
387 /*
388 #ifdef __WIN32__
389 // put the title string in bold face
390 if ( !m_title.IsEmpty() )
391 {
392 MENUITEMINFO mii;
393 mii.cbSize = sizeof(mii);
394 mii.fMask = MIIM_STATE;
395 mii.fState = MFS_DEFAULT;
396
397 if ( !SetMenuItemInfo(hMenu, (unsigned)idMenuTitle, FALSE, &mii) )
398 {
399 wxLogLastError("SetMenuItemInfo");
400 }
401 }
402 #endif // Win32
403 */
404 }
405
406 // ---------------------------------------------------------------------------
407 // event processing
408 // ---------------------------------------------------------------------------
409
410 bool wxMenu::OS2Command(WXUINT WXUNUSED(param), WXWORD id)
411 {
412 // ignore commands from the menu title
413
414 // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
415 if ( id != (WXWORD)idMenuTitle )
416 {
417 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
418 event.SetEventObject( this );
419 event.SetId( id );
420 event.SetInt( id );
421 ProcessCommand(event);
422 }
423
424 return TRUE;
425 }
426
427 bool wxMenu::ProcessCommand(wxCommandEvent & event)
428 {
429 bool processed = FALSE;
430
431 #if WXWIN_COMPATIBILITY
432 // Try a callback
433 if (m_callback)
434 {
435 (void)(*(m_callback))(*this, event);
436 processed = TRUE;
437 }
438 #endif // WXWIN_COMPATIBILITY
439
440 // Try the menu's event handler
441 if ( !processed && GetEventHandler())
442 {
443 processed = GetEventHandler()->ProcessEvent(event);
444 }
445
446 // Try the window the menu was popped up from (and up through the
447 // hierarchy)
448 wxWindow *win = GetInvokingWindow();
449 if ( !processed && win )
450 processed = win->GetEventHandler()->ProcessEvent(event);
451
452 return processed;
453 }
454
455 // ---------------------------------------------------------------------------
456 // other
457 // ---------------------------------------------------------------------------
458
459 void wxMenu::Attach(wxMenuBar *menubar)
460 {
461 // menu can be in at most one menubar because otherwise they would both
462 // delete the menu pointer
463 wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") );
464
465 m_menuBar = menubar;
466 }
467
468 void wxMenu::Detach()
469 {
470 wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
471
472 m_menuBar = NULL;
473 }
474
475 wxWindow *wxMenu::GetWindow() const
476 {
477 if ( m_invokingWindow != NULL )
478 return m_invokingWindow;
479 else if ( m_menuBar != NULL)
480 return m_menuBar->GetFrame();
481
482 return NULL;
483 }
484
485 // ---------------------------------------------------------------------------
486 // Menu Bar
487 // ---------------------------------------------------------------------------
488
489 void wxMenuBar::Init()
490 {
491 m_eventHandler = this;
492 m_menuBarFrame = NULL;
493 m_hMenu = 0;
494 }
495
496 wxMenuBar::wxMenuBar()
497 {
498 Init();
499 }
500
501 wxMenuBar::wxMenuBar( long WXUNUSED(style) )
502 {
503 Init();
504 }
505
506 wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
507 {
508 Init();
509
510 m_titles.Alloc(count);
511
512 for ( int i = 0; i < count; i++ )
513 {
514 m_menus.Append(menus[i]);
515 m_titles.Add(titles[i]);
516
517 menus[i]->Attach(this);
518 }
519 }
520
521 wxMenuBar::~wxMenuBar()
522 {
523 }
524
525 // ---------------------------------------------------------------------------
526 // wxMenuBar helpers
527 // ---------------------------------------------------------------------------
528
529 void wxMenuBar::Refresh(
530 bool WXUNUSED(bEraseBackground)
531 , const wxRect* WXUNUSED(pRect)
532 )
533 {
534 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
535
536 // DrawMenuBar(GetHwndOf(m_menuBarFrame));
537 }
538
539 WXHMENU wxMenuBar::Create()
540 {
541 if (m_hMenu != 0 )
542 return m_hMenu;
543
544 wxCHECK_MSG( !m_hMenu, TRUE, wxT("menubar already created") );
545
546 // TODO:
547 /*
548
549 m_hMenu = (WXHMENU)::CreateMenu();
550
551 if ( !m_hMenu )
552 {
553 wxLogLastError("CreateMenu");
554 }
555 else
556 {
557 size_t count = GetMenuCount();
558 for ( size_t i = 0; i < count; i++ )
559 {
560 if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING,
561 (UINT)m_menus[i]->GetHMenu(),
562 m_titles[i]) )
563 {
564 wxLogLastError("AppendMenu");
565 }
566 }
567 }
568
569 return m_hMenu;
570 */
571 return (WXHMENU)0;
572 }
573
574 // ---------------------------------------------------------------------------
575 // wxMenuBar functions to work with the top level submenus
576 // ---------------------------------------------------------------------------
577
578 // NB: we don't support owner drawn top level items for now, if we do these
579 // functions would have to be changed to use wxMenuItem as well
580
581 void wxMenuBar::EnableTop(size_t pos, bool enable)
582 {
583 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
584
585 // int flag = enable ? MF_ENABLED : MF_GRAYED;
586
587 // EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag);
588
589 Refresh();
590 }
591
592 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
593 {
594 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
595
596 m_titles[pos] = label;
597
598 if ( !IsAttached() )
599 {
600 return;
601 }
602 //else: have to modify the existing menu
603
604 // TODO:
605 /*
606 UINT id;
607 UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION);
608 if ( flagsOld == 0xFFFFFFFF )
609 {
610 wxLogLastError(wxT("GetMenuState"));
611
612 return;
613 }
614
615 if ( flagsOld & MF_POPUP )
616 {
617 // HIBYTE contains the number of items in the submenu in this case
618 flagsOld &= 0xff;
619 id = (UINT)::GetSubMenu((HMENU)m_hMenu, pos);
620 }
621 else
622 {
623 id = pos;
624 }
625
626 if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld,
627 id, label) == (int)0xFFFFFFFF )
628 {
629 wxLogLastError("ModifyMenu");
630 }
631 */
632 Refresh();
633 }
634
635 wxString wxMenuBar::GetLabelTop(size_t pos) const
636 {
637 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
638 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
639
640 return m_titles[pos];
641 }
642
643 int wxMenuBar::FindMenu(const wxString& title)
644 {
645 wxString menuTitle = wxStripMenuCodes(title);
646
647 size_t count = GetMenuCount();
648 for ( size_t i = 0; i < count; i++ )
649 {
650 wxString title = wxStripMenuCodes(m_titles[i]);
651 if ( menuTitle == title )
652 return i;
653 }
654
655 return wxNOT_FOUND;
656
657 }
658
659 // ---------------------------------------------------------------------------
660 // wxMenuBar construction
661 // ---------------------------------------------------------------------------
662
663 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
664 {
665 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
666 if ( !menuOld )
667 return FALSE;
668 m_titles[pos] = title;
669 // TODO:
670 /*
671 if ( IsAttached() )
672 {
673 // can't use ModifyMenu() because it deletes the submenu it replaces
674 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
675 {
676 wxLogLastError("RemoveMenu");
677 }
678
679 if ( !::InsertMenu(GetHmenu(), (UINT)pos,
680 MF_BYPOSITION | MF_POPUP | MF_STRING,
681 (UINT)GetHmenuOf(menu), title) )
682 {
683 wxLogLastError("InsertMenu");
684 }
685
686 #if wxUSE_ACCEL
687 if ( menuOld->HasAccels() || menu->HasAccels() )
688 {
689 // need to rebuild accell table
690 RebuildAccelTable();
691 }
692 #endif // wxUSE_ACCEL
693
694 Refresh();
695 }
696 */
697 return menuOld;
698 }
699
700 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
701 {
702 if ( !wxMenuBarBase::Insert(pos, menu, title) )
703 return FALSE;
704
705 m_titles.Insert(title, pos);
706
707 menu->Attach(this);
708 // TODO:
709 /*
710 if ( IsAttached() )
711 {
712 if ( !::InsertMenu(GetHmenu(), pos,
713 MF_BYPOSITION | MF_POPUP | MF_STRING,
714 (UINT)GetHmenuOf(menu), title) )
715 {
716 wxLogLastError("InsertMenu");
717 }
718
719 #if wxUSE_ACCEL
720 if ( menu->HasAccels() )
721 {
722 // need to rebuild accell table
723 RebuildAccelTable();
724 }
725 #endif // wxUSE_ACCEL
726
727 Refresh();
728 }
729 */
730 return TRUE;
731 }
732
733 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
734 {
735 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
736 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
737
738 if ( !wxMenuBarBase::Append(menu, title) )
739 return FALSE;
740
741 menu->Attach(this);
742
743 m_titles.Add(title);
744 // TODO:
745 /*
746 if ( IsAttached() )
747 {
748 if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
749 (UINT)submenu, title) )
750 {
751 wxLogLastError(wxT("AppendMenu"));
752 }
753
754 #if wxUSE_ACCEL
755 if ( menu->HasAccels() )
756 {
757 // need to rebuild accell table
758 RebuildAccelTable();
759 }
760 #endif // wxUSE_ACCEL
761
762 Refresh();
763 }
764 */
765 return TRUE;
766 }
767
768 wxMenu *wxMenuBar::Remove(size_t pos)
769 {
770 wxMenu *menu = wxMenuBarBase::Remove(pos);
771 if ( !menu )
772 return NULL;
773 // TODO:
774 /*
775 if ( IsAttached() )
776 {
777 if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
778 {
779 wxLogLastError("RemoveMenu");
780 }
781
782 menu->Detach();
783
784 #if wxUSE_ACCEL
785 if ( menu->HasAccels() )
786 {
787 // need to rebuild accell table
788 RebuildAccelTable();
789 }
790 #endif // wxUSE_ACCEL
791
792 Refresh();
793 }
794
795 m_titles.Remove(pos);
796 */
797 return menu;
798 }
799
800 #if wxUSE_ACCEL
801
802 void wxMenuBar::RebuildAccelTable()
803 {
804 // merge the accelerators of all menus into one accel table
805 size_t nAccelCount = 0;
806 size_t i, count = GetMenuCount();
807 for ( i = 0; i < count; i++ )
808 {
809 nAccelCount += m_menus[i]->GetAccelCount();
810 }
811
812 if ( nAccelCount )
813 {
814 wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount];
815
816 nAccelCount = 0;
817 for ( i = 0; i < count; i++ )
818 {
819 nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]);
820 }
821
822 m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries);
823
824 delete [] accelEntries;
825 }
826 }
827
828 #endif // wxUSE_ACCEL
829
830 void wxMenuBar::Attach(wxFrame *frame)
831 {
832 wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
833
834 m_menuBarFrame = frame;
835
836 #if wxUSE_ACCEL
837 RebuildAccelTable();
838 #endif // wxUSE_ACCEL
839 }
840
841 void wxMenuBar::Detach()
842 {
843 // ::DestroyMenu((HMENU)m_hMenu);
844 m_hMenu = (WXHMENU)NULL;
845 m_menuBarFrame = NULL;
846 }
847
848
849 // ---------------------------------------------------------------------------
850 // wxMenuBar searching for menu items
851 // ---------------------------------------------------------------------------
852
853 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
854 int wxMenuBar::FindMenuItem(const wxString& menuString,
855 const wxString& itemString) const
856 {
857 wxString menuLabel = wxStripMenuCodes(menuString);
858 size_t count = GetMenuCount();
859 for ( size_t i = 0; i < count; i++ )
860 {
861 wxString title = wxStripMenuCodes(m_titles[i]);
862 if ( menuString == title )
863 return m_menus[i]->FindItem(itemString);
864 }
865
866 return wxNOT_FOUND;
867 }
868
869 wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
870 {
871 if ( itemMenu )
872 *itemMenu = NULL;
873
874 wxMenuItem *item = NULL;
875 size_t count = GetMenuCount();
876 for ( size_t i = 0; !item && (i < count); i++ )
877 {
878 item = m_menus[i]->FindItem(id, itemMenu);
879 }
880
881 return item;
882 }
883