]> git.saurik.com Git - wxWidgets.git/blob - src/palmos/menu.cpp
compilation fixes for PalmOS and implementations of missing standard functions (pflib...
[wxWidgets.git] / src / palmos / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/palmos/menu.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: William Osborne - minimal working wxPalmOS port
5 // Modified by:
6 // Created: 10/12/04
7 // RCS-ID: $Id$
8 // Copyright: (c) William Osborne
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_MENUS
28
29 #include "wx/menu.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/frame.h"
33 #include "wx/utils.h"
34 #include "wx/intl.h"
35 #include "wx/log.h"
36 #endif
37
38 #if wxUSE_OWNER_DRAWN
39 #include "wx/ownerdrw.h"
40 #endif
41
42 #ifdef __WXPALMOS6__
43 #include <Loader.h>
44 #else // __WXPALMOS5__
45 #include <UIResources.h> // MenuRscType
46 #endif
47
48 #include <Form.h>
49 #include <Menu.h>
50
51 // ----------------------------------------------------------------------------
52 // global variables
53 // ----------------------------------------------------------------------------
54
55 extern wxMenu *wxCurrentPopupMenu;
56
57 // ----------------------------------------------------------------------------
58 // constants
59 // ----------------------------------------------------------------------------
60
61 // the (popup) menu title has this special id
62 static const int idMenuTitle = -3;
63
64 // ----------------------------------------------------------------------------
65 // private functions
66 // ----------------------------------------------------------------------------
67
68 // ============================================================================
69 // implementation
70 // ============================================================================
71
72 #include "wx/listimpl.cpp"
73
74 WX_DEFINE_LIST( wxMenuInfoList )
75
76 #if wxUSE_EXTENDED_RTTI
77
78 WX_DEFINE_FLAGS( wxMenuStyle )
79
80 wxBEGIN_FLAGS( wxMenuStyle )
81 wxFLAGS_MEMBER(wxMENU_TEAROFF)
82 wxEND_FLAGS( wxMenuStyle )
83
84 IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenu, wxEvtHandler,"wx/menu.h")
85
86 wxCOLLECTION_TYPE_INFO( wxMenuItem * , wxMenuItemList ) ;
87
88 template<> void wxCollectionToVariantArray( wxMenuItemList const &theList, wxxVariantArray &value)
89 {
90 wxListCollectionToVariantArray<wxMenuItemList::compatibility_iterator>( theList , value ) ;
91 }
92
93 wxBEGIN_PROPERTIES_TABLE(wxMenu)
94 wxEVENT_PROPERTY( Select , wxEVT_COMMAND_MENU_SELECTED , wxCommandEvent)
95 wxPROPERTY( Title, wxString , SetTitle, GetTitle, wxString(), 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
96 wxREADONLY_PROPERTY_FLAGS( MenuStyle , wxMenuStyle , long , GetStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
97 wxPROPERTY_COLLECTION( MenuItems , wxMenuItemList , wxMenuItem* , Append , GetMenuItems , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
98 wxEND_PROPERTIES_TABLE()
99
100 wxBEGIN_HANDLERS_TABLE(wxMenu)
101 wxEND_HANDLERS_TABLE()
102
103 wxDIRECT_CONSTRUCTOR_2( wxMenu , wxString , Title , long , MenuStyle )
104
105 WX_DEFINE_FLAGS( wxMenuBarStyle )
106
107 wxBEGIN_FLAGS( wxMenuBarStyle )
108 wxFLAGS_MEMBER(wxMB_DOCKABLE)
109 wxEND_FLAGS( wxMenuBarStyle )
110
111 // the negative id would lead the window (its superclass !) to vetoe streaming out otherwise
112 bool wxMenuBarStreamingCallback( const wxObject *WXUNUSED(object), wxWriter * , wxPersister * , wxxVariantArray & )
113 {
114 return true ;
115 }
116
117 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuBar, wxWindow ,"wx/menu.h",wxMenuBarStreamingCallback)
118
119 IMPLEMENT_DYNAMIC_CLASS_XTI(wxMenuInfo, wxObject , "wx/menu.h" )
120
121 wxBEGIN_PROPERTIES_TABLE(wxMenuInfo)
122 wxREADONLY_PROPERTY( Menu , wxMenu* , GetMenu , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
123 wxREADONLY_PROPERTY( Title , wxString , GetTitle , wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
124 wxEND_PROPERTIES_TABLE()
125
126 wxBEGIN_HANDLERS_TABLE(wxMenuInfo)
127 wxEND_HANDLERS_TABLE()
128
129 wxCONSTRUCTOR_2( wxMenuInfo , wxMenu* , Menu , wxString , Title )
130
131 wxCOLLECTION_TYPE_INFO( wxMenuInfo * , wxMenuInfoList ) ;
132
133 template<> void wxCollectionToVariantArray( wxMenuInfoList const &theList, wxxVariantArray &value)
134 {
135 wxListCollectionToVariantArray<wxMenuInfoList::compatibility_iterator>( theList , value ) ;
136 }
137
138 wxBEGIN_PROPERTIES_TABLE(wxMenuBar)
139 wxPROPERTY_COLLECTION( MenuInfos , wxMenuInfoList , wxMenuInfo* , Append , GetMenuInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
140 wxEND_PROPERTIES_TABLE()
141
142 wxBEGIN_HANDLERS_TABLE(wxMenuBar)
143 wxEND_HANDLERS_TABLE()
144
145 wxCONSTRUCTOR_DUMMY( wxMenuBar )
146
147 #else
148 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
149 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow)
150 IMPLEMENT_DYNAMIC_CLASS(wxMenuInfo, wxObject)
151 #endif
152
153 const wxMenuInfoList& wxMenuBar::GetMenuInfos() const
154 {
155 wxMenuInfoList* list = const_cast< wxMenuInfoList* >( &m_menuInfos ) ;
156 WX_CLEAR_LIST( wxMenuInfoList , *list ) ;
157 for( size_t i = 0 ; i < GetMenuCount() ; ++i )
158 {
159 wxMenuInfo* info = new wxMenuInfo() ;
160 info->Create( const_cast<wxMenuBar*>(this)->GetMenu(i) , GetMenuLabel(i) ) ;
161 list->Append( info ) ;
162 }
163 return m_menuInfos ;
164 }
165
166 // ---------------------------------------------------------------------------
167 // wxMenu construction, adding and removing menu items
168 // ---------------------------------------------------------------------------
169
170 // Construct a menu with optional title (then use append)
171 void wxMenu::Init()
172 {
173 }
174
175 // The wxWindow destructor will take care of deleting the submenus.
176 wxMenu::~wxMenu()
177 {
178 }
179
180 void wxMenu::Break()
181 {
182 }
183
184 void wxMenu::Attach(wxMenuBarBase *menubar)
185 {
186 wxMenuBase::Attach(menubar);
187 }
188
189 #if wxUSE_ACCEL
190
191 int wxMenu::FindAccel(int id) const
192 {
193 return wxNOT_FOUND;
194 }
195
196 void wxMenu::UpdateAccel(wxMenuItem *item)
197 {
198 }
199
200 #endif // wxUSE_ACCEL
201
202 // append a new item or submenu to the menu
203 bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
204 {
205 if ( IsAttached() && GetMenuBar()->IsAttached() )
206 {
207 // Regenerate the menu resource
208 GetMenuBar()->Refresh();
209 }
210
211 return true;
212 }
213
214 void wxMenu::EndRadioGroup()
215 {
216 }
217
218 wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
219 {
220 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
221
222 if(!wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item))
223 {
224 return NULL;
225 }
226 else if(IsAttached() && GetMenuBar()->IsAttached())
227 {
228 // Regenerate the menu resource
229 GetMenuBar()->Refresh();
230 }
231
232 return item;
233 }
234
235 wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
236 {
237 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
238 return item;
239 else
240 return NULL;
241 }
242
243 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
244 {
245 // we need to find the items position in the child list
246 size_t pos;
247 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
248 for ( pos = 0; node; pos++ )
249 {
250 if ( node->GetData() == item )
251 break;
252
253 node = node->GetNext();
254 }
255
256 // DoRemove() (unlike Remove) can only be called for existing item!
257 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
258
259 // remove the item from the menu
260 wxMenuItem *ret=wxMenuBase::DoRemove(item);
261
262 if ( IsAttached() && GetMenuBar()->IsAttached() )
263 {
264 // Regenerate the menu resource
265 GetMenuBar()->Refresh();
266 }
267
268 return ret;
269 }
270
271 // ---------------------------------------------------------------------------
272 // accelerator helpers
273 // ---------------------------------------------------------------------------
274
275 #if wxUSE_ACCEL
276
277 // create the wxAcceleratorEntries for our accels and put them into provided
278 // array - return the number of accels we have
279 size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
280 {
281 size_t count = GetAccelCount();
282 for ( size_t n = 0; n < count; n++ )
283 {
284 *accels++ = *m_accels[n];
285 }
286
287 return count;
288 }
289
290 #endif // wxUSE_ACCEL
291
292 // ---------------------------------------------------------------------------
293 // set wxMenu title
294 // ---------------------------------------------------------------------------
295
296 void wxMenu::SetTitle(const wxString& label)
297 {
298 m_title = label;
299
300 if ( IsAttached() && GetMenuBar()->IsAttached() )
301 {
302 // Regenerate the menu resource
303 GetMenuBar()->Refresh();
304 }
305 }
306
307 // ---------------------------------------------------------------------------
308 // event processing
309 // ---------------------------------------------------------------------------
310
311 bool wxMenu::PalmCommand(WXUINT WXUNUSED(param), WXWORD id)
312 {
313 return false;
314 }
315
316 // ---------------------------------------------------------------------------
317 // other
318 // ---------------------------------------------------------------------------
319
320 wxWindow *wxMenu::GetWindow() const
321 {
322 return NULL;
323 }
324
325 // ---------------------------------------------------------------------------
326 // Menu Bar
327 // ---------------------------------------------------------------------------
328
329 void wxMenuBar::Init()
330 {
331 }
332
333 wxMenuBar::wxMenuBar()
334 {
335 }
336
337 wxMenuBar::wxMenuBar( long WXUNUSED(style) )
338 {
339 }
340
341 wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
342 {
343 }
344
345 wxMenuBar::~wxMenuBar()
346 {
347 }
348
349 // ---------------------------------------------------------------------------
350 // wxMenuBar helpers
351 // ---------------------------------------------------------------------------
352
353 void wxMenuBar::Refresh()
354 {
355 wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") );
356
357 // Regenerate the menu resource
358 LoadMenu();
359 }
360
361 WXHMENU wxMenuBar::Create()
362 {
363 return NULL;
364 }
365
366 int wxMenuBar::PalmPositionForWxMenu(wxMenu *menu, int wxpos)
367 {
368 return -1;
369 }
370
371 // ---------------------------------------------------------------------------
372 // wxMenuBar functions to work with the top level submenus
373 // ---------------------------------------------------------------------------
374
375 void wxMenuBar::EnableTop(size_t pos, bool enable)
376 {
377 // Palm OS does not have support for grayed or disabled items
378 }
379
380 void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
381 {
382 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
383
384 m_titles[pos] = label;
385
386 if ( !IsAttached() )
387 {
388 return;
389 }
390
391 // Regenerate the menu resource
392 Refresh();
393 }
394
395 wxString wxMenuBar::GetMenuLabel(size_t pos) const
396 {
397 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
398 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
399
400 return m_titles[pos];
401 }
402
403 // ---------------------------------------------------------------------------
404 // wxMenuBar construction
405 // ---------------------------------------------------------------------------
406
407 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
408 {
409 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
410 if ( !menuOld )
411 return NULL;
412
413 m_titles[pos] = title;
414
415 if ( IsAttached() )
416 {
417 // Regenerate the menu resource
418 Refresh();
419 }
420
421 return menuOld;
422 }
423
424 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
425 {
426 if ( !wxMenuBarBase::Insert(pos, menu, title) )
427 return false;
428
429 m_titles.Insert(title, pos);
430
431 if ( IsAttached() )
432 {
433 // Regenerate the menu resource
434 Refresh();
435 }
436
437 return true;
438 }
439
440 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
441 {
442 if ( !wxMenuBarBase::Append(menu, title) )
443 return false;
444
445 m_titles.Add(title);
446
447 if(IsAttached())
448 {
449 // Regenerate the menu resource
450 Refresh();
451 }
452
453 return true;
454 }
455
456 wxMenu *wxMenuBar::Remove(size_t pos)
457 {
458 wxMenu *menu = wxMenuBarBase::Remove(pos);
459 if ( !menu )
460 return NULL;
461
462 m_titles.RemoveAt(pos);
463
464 if (IsAttached())
465 {
466 // Regenerate the menu resource
467 Refresh();
468 }
469
470 return menu;
471 }
472
473 #if wxUSE_ACCEL
474
475 void wxMenuBar::RebuildAccelTable()
476 {
477 }
478
479 #endif // wxUSE_ACCEL
480
481 int wxMenuBar::ProcessCommand(int ItemID)
482 {
483 if(!IsAttached())
484 return -1;
485
486 int MenuNum=(ItemID/1000)-1;
487 int ItemNum=(ItemID-(1000*(MenuNum+1)));
488
489 // Should never happen, but it doesn't hurt to check anyway.
490 if(MenuNum>GetMenuCount())
491 return -1;
492
493 // Get the menu
494 wxMenu *ActiveMenu=GetMenu(MenuNum);
495
496 // Make sure this is a valid item.
497 if(ItemNum>ActiveMenu->GetMenuItemCount())
498 return -1;
499
500 // Get the item
501 wxMenuItem *ActiveItem=ActiveMenu->FindItemByPosition(ItemNum);
502 int ActiveID=ActiveItem->GetId();
503
504 return ActiveID;
505 }
506
507 /* Palm OS does not have good dynamic menu support. About all you can do with
508 * the standard API calls is to add new items to an existing drop-down menu and
509 * hide/show items in a drop-down menu. It is impossible to add, hide, or
510 * change the label on a drop-down menu.
511 *
512 * The easiest and simplest way around this limitation is to modify the Palm OS
513 * MenuBarType structure directly. This gives limited ability to change the
514 * label on a drop-down menu. I have not been able to find a safe way to add,
515 * delete, or resize drop-down menus in OS 6.
516 *
517 * The following routine attempt to work around these limitations present in the
518 * Palm OS API to provide limited dynamic menu support. This solution is far
519 * from perfect, but the only other option is to wait for PalmSource to add full
520 * dynamic menu support, or to recreate the Palm OS menu system from scratch.
521 *
522 * This system is limited in that no more than 4 drop-down menus are allowed per
523 * menu bar, and the label for each drop-down menu is limited to 8 characters of
524 * text. However, this menu system should work for most applications.
525 *
526 * Basically the menu routines select one of four menu bars, depending on
527 * whether or not the requested menu bar has one, two, three, or four drop-down
528 * menus.
529 *
530 * These four "template" menu bars contain one, two, three, or four drop-down
531 * menus. Each menu has a dummy menu item attached to it to allow the Palm OS
532 * MenuAddItem function to add the real items.
533 *
534 * The labels on the drop-down menus are then replaced with the labels of the
535 * real menus.
536 *
537 * The menu is then attached to the active window and the MenuAddItem API
538 * function is called to add the items to each drop-down menu. Finally,
539 * MenuHideItem is called to remove the dummy items from each drop-down menu.
540 */
541 void wxMenuBar::LoadMenu()
542 {
543 int i=0;
544 int j=0;
545 #ifdef __WXPALMOS6__
546 // Handle to the currently running application database
547 DmOpenRef AppDB;
548
549 // Get app database reference - needed for some Palm OS Menu API calls.
550 SysGetModuleDatabase(SysGetRefNum(), NULL, &AppDB);
551 #endif // __WXPALMOS6__
552
553 // Get the number of menus
554 int NumMenus=GetMenuCount();
555
556 // Set up the pointers and handles
557 char *PalmOSMenuBarPtr;
558 MemHandle PalmOSMenuBar;
559
560 // Load the menu template and set up the menu pointers
561 if(NumMenus==1)
562 {
563 PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 1000);
564 PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar);
565
566 PalmOSMenuBarPtr += 74;
567 }
568 else if(NumMenus==2)
569 {
570 PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 2000);
571 PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar);
572
573 PalmOSMenuBarPtr += 116;
574 }
575 else if(NumMenus==3)
576 {
577 PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 3000);
578 PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar);
579
580 PalmOSMenuBarPtr += 158;
581 }
582 else
583 {
584 // We support a maximum of 4 menus, so make sure that do not create
585 // more than we can handle.
586 NumMenus=4;
587
588 PalmOSMenuBar = POS_DmGetResource (AppDB, MenuRscType, 4000);
589 PalmOSMenuBarPtr = (char *)MemHandleLock (PalmOSMenuBar);
590
591 PalmOSMenuBarPtr += 200;
592 }
593
594 // Set the proper names for the drop-down triggers.
595 for(i=0;i<NumMenus;i++)
596 {
597 // Clear out the old label
598 char buffer[8]={' ',' ',' ',' ',' ',' ',' ',' '};
599 MemMove(PalmOSMenuBarPtr,buffer,8);
600
601 wxString MenuTitle=m_titles.Item(i);
602
603 // Make sure we don't copy more than 8 bytes for the label
604 int LengthToCopy = MenuTitle.length();
605 if(LengthToCopy > 8)
606 LengthToCopy = 8;
607
608 MemMove(PalmOSMenuBarPtr,(char*)(&MenuTitle),LengthToCopy);
609 PalmOSMenuBarPtr+=11;
610 }
611
612 // We are done with the menu pointer.
613 MemHandleUnlock(PalmOSMenuBar);
614 DmReleaseResource(PalmOSMenuBar);
615
616 // We must make the menu active before we can add items to the drop-down
617 // triggers.
618 POS_FrmSetMenu (FrmGetActiveForm(), AppDB, NumMenus * 1000);
619
620 /* Add the menu items to the drop-down triggers. This must be done after
621 * setting the triggers, because setting the names of drop-down triggers
622 * that have a variable number of items requires carefull calculation of
623 * the offsets in the MenuBarType structure. Setting the triggers first
624 * avoids this.
625 */
626 for(i=0;i<NumMenus;i++)
627 {
628 wxMenu *CurrentMenu=GetMenu(i);
629
630 for(j=0;j<CurrentMenu->GetMenuItemCount();j++)
631 {
632 wxMenuItem *CurrentItem=CurrentMenu->FindItemByPosition(j);
633 wxString ItemLabel=CurrentItem->GetLabel();
634
635 if(CurrentItem->IsSeparator()==true)
636 {
637 char Separator=MenuSeparatorChar;
638 if(j==0)
639 MenuAddItem(9000+i,((i*1000)+1000)+j,0x00,&Separator);
640 else
641 MenuAddItem(((i*1000)+1000)+j-1,((i*1000)+1000)+j,0x00,&Separator);
642 }
643 else
644 {
645 if(j==0)
646 MenuAddItem(9000+i,((i*1000)+1000)+j,0x00,(char *)(&ItemLabel));
647 else
648 MenuAddItem(((i*1000)+1000)+j-1,((i*1000)+1000)+j,0x00,(char *)(&ItemLabel));
649 }
650 }
651
652 // Hide the dummy menu item, since we don't need it anymore.
653 MenuHideItem(9000+i);
654 }
655 }
656
657 void wxMenuBar::Attach(wxFrame *frame)
658 {
659 // before attaching preprocess menus to not include wxID_EXIT item
660 // as PalmOS guidelines suggest
661
662 wxMenuItem *item;
663 wxMenu *menu;
664 int i;
665
666 while( item = FindItem(wxID_EXIT) )
667 {
668 menu = item->GetMenu();
669 if( !menu ) break; // something broken ?
670
671 size_t count = menu->GetMenuItemCount();
672 if( count == 0 ) break; // something broken ?
673
674 // if EXIT is last item in menu
675 if( menu->FindItemByPosition( count - 1 ) == item )
676 {
677 menu->Destroy( item );
678
679 // was more than one item?
680 // was previous separator ?
681 if( count > 2 )
682 {
683 item = menu->FindItemByPosition( count - 2 );
684 if(item && item->IsSeparator())
685 menu->Destroy( item );
686 }
687 }
688
689 // if EXIT is first item in menu
690 else if( menu->FindItemByPosition( 0 ) == item )
691 {
692 menu->Destroy( item );
693
694 // was more than one item?
695 // was previous separator ?
696 if( count > 2 )
697 {
698 item = menu->FindItemByPosition( 0 );
699 if(item && item->IsSeparator())
700 menu->Destroy( item );
701 }
702 }
703
704 // if EXIT is in the middle but before and after are selectors
705 else
706 {
707 i = 1; // 0 case already done
708 while ( (i < count) && (menu->FindItemByPosition( 0 ) != item) )
709 {
710 i++;
711 }
712
713 if (i >= count) break;
714 if (menu->FindItemByPosition( i ) != item) break;
715 menu->Destroy( item );
716 item = menu->FindItemByPosition( i );
717 if ( item &&
718 item->IsSeparator() &&
719 menu->FindItemByPosition( i-1 )->IsSeparator() )
720 {
721 // noe need for two neighbouring separators
722 menu->Destroy( item );
723 }
724 }
725 }
726
727 // check if we received any empty menu!
728 i = 0;
729 while(i < GetMenuCount())
730 {
731 menu = GetMenu(i);
732
733 if( menu && (menu->GetMenuItemCount()==0) )
734 {
735 menu = Remove( i );
736 delete menu;
737 }
738 else
739 i++;
740 }
741
742 wxMenuBarBase::Attach(frame);
743
744 LoadMenu();
745 }
746
747 void wxMenuBar::Detach()
748 {
749 wxMenuBarBase::Detach();
750 }
751
752 #endif // wxUSE_MENUS