1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/ownerdrw.h"
26 #include "wx/os2/private.h"
28 #include "wx/menuitem.h"
31 // other standard headers
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 extern wxMenu
*wxCurrentPopupMenu
;
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 // the (popup) menu title has this special id
45 static const int idMenuTitle
= -2;
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 #if !USE_SHARED_LIBRARY
52 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
53 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
56 // ============================================================================
58 // ============================================================================
60 // ---------------------------------------------------------------------------
61 // wxMenu construction, adding and removing menu items
62 // ---------------------------------------------------------------------------
64 // Construct a menu with optional title (then use append)
65 void wxMenu::Init(const wxString
& title
, const wxFunction func
)
69 m_eventHandler
= this;
70 m_pInvokingWindow
= NULL
;
74 m_hMenu
= 0; //(WXHMENU) CreatePopupMenu();
76 m_topLevelMenu
= this;
77 m_clientData
= (void*) NULL
;
81 Append(idMenuTitle
, m_title
) ;
88 // The wxWindow destructor will take care of deleting the submenus.
91 // free Windows resources
94 // ::DestroyMenu((HMENU)m_hMenu);
99 wxNode
*node
= m_menuItems
.First();
102 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
104 // Delete child menus.
105 // Beware: they must not be appended to children list!!!
106 // (because order of delete is significant)
107 if ( item
->IsSubMenu() )
108 item
->DeleteSubMenu();
110 wxNode
*next
= node
->Next();
122 // function appends a new item or submenu to the menu
123 void wxMenu::Append(wxMenuItem
*pItem
)
125 wxCHECK_RET( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
128 // check for accelerators: they are given after '\t'
129 wxString label
= pItem
->GetName();
130 int posTab
= label
.Find(wxT('\t'));
131 if ( posTab
!= wxNOT_FOUND
) {
132 // parse the accelerator string
134 int accelFlags
= wxACCEL_NORMAL
;
136 for ( size_t n
= (size_t)posTab
+ 1; n
< label
.Len(); n
++ ) {
137 if ( (label
[n
] == '+') || (label
[n
] == '-') ) {
138 if ( current
== _("ctrl") )
139 accelFlags
|= wxACCEL_CTRL
;
140 else if ( current
== _("alt") )
141 accelFlags
|= wxACCEL_ALT
;
142 else if ( current
== _("shift") )
143 accelFlags
|= wxACCEL_SHIFT
;
145 wxLogDebug(wxT("Unknown accel modifier: '%s'"),
152 current
+= wxTolower(label
[n
]);
156 if ( current
.IsEmpty() ) {
157 wxLogDebug(wxT("No accel key found, accel string ignored."));
160 if ( current
.Len() == 1 ) {
162 keyCode
= wxToupper(current
[0U]);
165 // it should be a function key
166 if ( current
[0U] == 'f' && isdigit(current
[1U]) &&
167 (current
.Len() == 2 ||
168 (current
.Len() == 3 && isdigit(current
[2U]))) ) {
170 wxSscanf(current
.c_str() + 1, wxT("%d"), &n
);
172 keyCode
= VK_F1
+ n
- 1;
175 wxLogDebug(wxT("Unrecognized accel key '%s', accel "
176 "string ignored."), current
.c_str());
183 m_accelKeyCodes
.Add(keyCode
);
184 m_accelFlags
.Add(accelFlags
);
185 m_accelIds
.Add(pItem
->GetId());
188 #endif // wxUSE_ACCEL
194 // if "Break" has just been called, insert a menu break before this item
195 // (and don't forget to reset the flag)
197 flags |= MF_MENUBREAK;
201 if ( pItem->IsSeparator() ) {
202 flags |= MF_SEPARATOR;
205 // id is the numeric id for normal menu items and HMENU for submenus as
206 // required by ::AppendMenu() API
208 wxMenu *submenu = pItem->GetSubMenu();
209 if ( submenu != NULL ) {
210 wxASSERT( submenu->GetHMenu() != (WXHMENU) NULL );
212 id = (UINT)submenu->GetHMenu();
213 submenu->m_topLevelMenu = m_topLevelMenu;
214 submenu->m_parent = this;
215 submenu->m_savehMenu = (WXHMENU)id;
216 submenu->m_hMenu = 0;
226 #if wxUSE_OWNER_DRAWN
227 if ( pItem->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
228 // item draws itself, pass pointer to it in data parameter
229 flags |= MF_OWNERDRAW;
230 pData = (const char*)pItem;
235 // menu is just a normal string (passed in data parameter)
239 if ( !::AppendMenu(GetHmenu(), flags, id, pData) )
241 wxLogLastError("AppendMenu");
245 if ( id == idMenuTitle )
247 // visually select the menu title
249 mii.cbSize = sizeof(mii);
250 mii.fMask = MIIM_STATE;
251 mii.fState = MFS_DEFAULT;
253 if ( !SetMenuItemInfo(GetHmenu(), (unsigned)id, FALSE, &mii) )
255 wxLogLastError(wxT("SetMenuItemInfo"));
258 m_menuItems.Append(pItem);
264 void wxMenu::AppendSeparator()
266 Append(new wxMenuItem(this, ID_SEPARATOR
));
270 void wxMenu::Append(int id
,
271 const wxString
& label
,
273 const wxString
& helpString
)
275 Append(new wxMenuItem(this, id
, label
, helpString
, FALSE
, SubMenu
));
278 // Ordinary menu item
279 void wxMenu::Append(int id
,
280 const wxString
& label
,
281 const wxString
& helpString
,
284 // 'checkable' parameter is useless for Windows.
285 Append(new wxMenuItem(this, id
, label
, helpString
, checkable
));
289 void wxMenu::Delete(int id
)
291 wxMenuItem
*item
= NULL
;
294 for (pos
= 0, node
= m_menuItems
.First(); node
; node
= node
->Next(), pos
++)
296 item
= (wxMenuItem
*)node
->Data();
297 if ( item
->GetId() == id
)
301 wxCHECK_RET( node
, wxT("wxMenu::Delete(): item doesn't exist") );
303 HMENU menu
= GetHmenu();
305 wxMenu
*pSubMenu
= item
->GetSubMenu();
306 if ( pSubMenu
!= NULL
)
308 // RemoveMenu(menu, (UINT)pos, MF_BYPOSITION);
309 pSubMenu
->m_hMenu
= pSubMenu
->m_savehMenu
;
310 pSubMenu
->m_savehMenu
= 0;
311 pSubMenu
->m_parent
= NULL
;
312 // RemoveChild(item->subMenu);
313 pSubMenu
->m_topLevelMenu
= NULL
;
314 // TODO: Why isn't subMenu deleted here???
315 // Will put this in for now. Assuming this is supposed
316 // to delete the menu, not just remove it.
317 item
->DeleteSubMenu();
321 // DeleteMenu(menu, (UINT)pos, MF_BYPOSITION);
324 m_menuItems
.DeleteNode(node
);
330 // ---------------------------------------------------------------------------
331 // accelerator helpers
332 // ---------------------------------------------------------------------------
334 // create the wxAcceleratorEntries for our accels and put them into provided
335 // array - return the number of accels we have
336 size_t wxMenu::CopyAccels(wxAcceleratorEntry
*accels
) const
338 size_t count
= GetAccelCount();
339 for ( size_t n
= 0; n
< count
; n
++ )
341 (*accels
++).Set(m_accelFlags
[n
], m_accelKeyCodes
[n
], m_accelIds
[n
]);
347 #endif // wxUSE_ACCEL
349 // ---------------------------------------------------------------------------
350 // wxMenu functions implemented in wxMenuItem
351 // ---------------------------------------------------------------------------
353 void wxMenu::Enable(int id
, bool Flag
)
355 wxMenuItem
*item
= FindItemForId(id
);
356 wxCHECK_RET( item
!= NULL
, wxT("can't enable non-existing menu item") );
361 bool wxMenu::IsEnabled(int id
) const
363 wxMenuItem
*item
= FindItemForId(id
);
364 wxCHECK_MSG( item
!= NULL
, FALSE
, wxT("invalid item id") );
366 return item
->IsEnabled();
369 void wxMenu::Check(int id
, bool Flag
)
371 wxMenuItem
*item
= FindItemForId(id
);
372 wxCHECK_RET( item
!= NULL
, wxT("can't get status of non-existing menu item") );
377 bool wxMenu::IsChecked(int id
) const
379 wxMenuItem
*item
= FindItemForId(id
);
380 wxCHECK_MSG( item
!= NULL
, FALSE
, wxT("invalid item id") );
382 return item
->IsChecked();
385 void wxMenu::SetLabel(int id
, const wxString
& label
)
387 wxMenuItem
*item
= FindItemForId(id
) ;
388 wxCHECK_RET( item
, wxT("wxMenu::SetLabel: no such item") );
390 item
->SetName(label
);
393 wxString
wxMenu::GetLabel(int id
) const
396 wxMenuItem
*pItem
= FindItemForId(id
) ;
398 label
= pItem
->GetName() ;
400 wxFAIL_MSG(wxT("wxMenu::GetLabel: item doesn't exist"));
405 void wxMenu::SetHelpString(int itemId
, const wxString
& helpString
)
407 wxMenuItem
*item
= FindItemForId (itemId
);
409 item
->SetHelp(helpString
);
411 wxFAIL_MSG(wxT("wxMenu::SetHelpString: item doesn't exist"));
414 wxString
wxMenu::GetHelpString (int itemId
) const
417 wxMenuItem
*item
= FindItemForId (itemId
);
419 help
= item
->GetHelp();
421 wxFAIL_MSG(wxT("wxMenu::GetHelpString: item doesn't exist"));
426 // ---------------------------------------------------------------------------
428 // ---------------------------------------------------------------------------
430 void wxMenu::SetTitle(const wxString
& label
)
432 bool hasNoTitle
= m_title
.IsEmpty();
435 HMENU hMenu
= GetHmenu();
440 if ( !label.IsEmpty() )
442 if ( !InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
443 (unsigned)idMenuTitle, m_title) ||
444 !InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
446 wxLogLastError(wxT("InsertMenu"));
452 if ( label.IsEmpty() )
454 // remove the title and the separator after it
455 if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) ||
456 !RemoveMenu(hMenu, 0, MF_BYPOSITION) )
458 wxLogLastError("RemoveMenu");
464 if ( !ModifyMenu(hMenu, 0u,
465 MF_BYPOSITION | MF_STRING,
466 (unsigned)idMenuTitle, m_title) )
468 wxLogLastError("ModifyMenu");
473 // put the title string in bold face
474 if ( !m_title.IsEmpty() )
477 mii.cbSize = sizeof(mii);
478 mii.fMask = MIIM_STATE;
479 mii.fState = MFS_DEFAULT;
481 if ( !SetMenuItemInfo(hMenu, (unsigned)idMenuTitle, FALSE, &mii) )
483 wxLogLastError("SetMenuItemInfo");
489 const wxString
wxMenu::GetTitle() const
494 // ---------------------------------------------------------------------------
496 // ---------------------------------------------------------------------------
498 bool wxMenu::OS2Command(WXUINT
WXUNUSED(param
), WXWORD id
)
500 // ignore commands from the menu title
502 if ( id
!= (WXWORD
)idMenuTitle
)
504 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
505 event
.SetEventObject( this );
508 ProcessCommand(event
);
514 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
516 bool processed
= FALSE
;
521 (void)(*(m_callback
))(*this, event
);
525 // Try the menu's event handler
526 if ( !processed
&& GetEventHandler())
528 processed
= GetEventHandler()->ProcessEvent(event
);
531 // Try the window the menu was popped up from (and up through the
533 wxWindow
*win
= GetInvokingWindow();
534 if ( !processed
&& win
)
535 processed
= win
->GetEventHandler()->ProcessEvent(event
);
540 // ---------------------------------------------------------------------------
542 // ---------------------------------------------------------------------------
544 // Finds the item id matching the given string, -1 if not found.
545 int wxMenu::FindItem (const wxString
& itemString
) const
547 wxString itemLabel
= wxStripMenuCodes(itemString
);
548 for ( wxNode
*node
= m_menuItems
.First(); node
; node
= node
->Next() )
550 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
551 if ( item
->IsSubMenu() )
553 int ans
= item
->GetSubMenu()->FindItem(itemString
);
554 if ( ans
!= wxNOT_FOUND
)
557 else if ( !item
->IsSeparator() )
559 wxString label
= wxStripMenuCodes(item
->GetName());
560 if ( itemLabel
== label
)
561 return item
->GetId();
568 wxMenuItem
*wxMenu::FindItemForId(int itemId
, wxMenu
** itemMenu
) const
573 wxMenuItem
*item
= NULL
;
574 for ( wxNode
*node
= m_menuItems
.First(); node
&& !item
; node
= node
->Next() )
576 item
= (wxMenuItem
*)node
->Data();
578 if ( item
->GetId() == itemId
)
581 *itemMenu
= (wxMenu
*)this;
583 else if ( item
->IsSubMenu() )
585 item
= item
->GetSubMenu()->FindItemForId(itemId
, itemMenu
);
589 // don't exit the loop
597 // ---------------------------------------------------------------------------
599 // ---------------------------------------------------------------------------
601 void wxMenu::Attach(wxMenuBar
*menubar
)
603 // menu can be in at most one menubar because otherwise they would both
604 // delete the menu pointer
605 wxASSERT_MSG( !m_menuBar
, wxT("menu belongs to 2 menubars, expect a crash") );
608 m_savehMenu
= m_hMenu
;
612 void wxMenu::Detach()
614 wxASSERT_MSG( m_menuBar
, wxT("can't detach menu if it's not attached") );
616 m_hMenu
= m_savehMenu
;
620 // ---------------------------------------------------------------------------
622 // ---------------------------------------------------------------------------
624 void wxMenuBar::Init()
626 m_eventHandler
= this;
630 m_menuBarFrame
= NULL
;
634 wxMenuBar::wxMenuBar()
639 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
644 wxMenuBar::wxMenuBar(int count
, wxMenu
*menus
[], const wxString titles
[])
650 m_titles
= new wxString
[count
];
653 for ( i
= 0; i
< count
; i
++ )
654 m_titles
[i
] = titles
[i
];
656 for ( i
= 0; i
< count
; i
++ )
657 m_menus
[i
]->Attach(this);
660 wxMenuBar::~wxMenuBar()
662 for ( int i
= 0; i
< m_menuCount
; i
++ )
671 // ---------------------------------------------------------------------------
673 // ---------------------------------------------------------------------------
675 void wxMenuBar::Refresh()
677 wxCHECK_RET( m_menuBarFrame
, wxT("can't refresh a menubar withotu a frame") );
679 // TODO DrawMenuBar((HWND)m_menuBarFrame->GetHWND()) ;
682 WXHMENU
wxMenuBar::Create()
687 wxCHECK_MSG( !m_hMenu
, TRUE
, wxT("menubar already created") );
689 m_hMenu
= 0; // TODO: (WXHMENU)::CreateMenu();
693 wxLogLastError("CreateMenu");
697 for ( int i
= 0; i
< m_menuCount
; i
++ )
699 // if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING,
700 // (UINT)m_menus[i]->GetHMenu(),
703 // wxLogLastError("AppendMenu");
711 // ---------------------------------------------------------------------------
712 // wxMenuBar functions forwarded to wxMenuItem
713 // ---------------------------------------------------------------------------
715 // Must only be used AFTER menu has been attached to frame,
716 // otherwise use individual menus to enable/disable items
717 void wxMenuBar::Enable(int id
, bool enable
)
719 wxMenu
*itemMenu
= NULL
;
720 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
722 wxCHECK_RET( item
, wxT("attempt to enable an item which doesn't exist") );
724 item
->Enable(enable
);
727 void wxMenuBar::EnableTop(int pos
, bool enable
)
729 int flag
= 0; // TODO enable ? MF_ENABLED : MF_GRAYED;;
731 // EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag);
734 // Must only be used AFTER menu has been attached to frame,
735 // otherwise use individual menus
736 void wxMenuBar::Check(int id
, bool check
)
738 wxMenu
*itemMenu
= NULL
;
739 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
741 wxCHECK_RET( item
, wxT("attempt to check an item which doesn't exist") );
742 wxCHECK_RET( item
->IsCheckable(), wxT("attempt to check an uncheckable item") );
747 bool wxMenuBar::IsChecked(int id
) const
749 wxMenu
*itemMenu
= NULL
;
750 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
752 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsChecked(): no such item") );
754 // int flag = ::GetMenuState(GetHmenuOf(itemMenu), id, MF_BYCOMMAND);
756 // return (flag & MF_CHECKED) != 0;
760 bool wxMenuBar::IsEnabled(int id
) const
762 wxMenu
*itemMenu
= NULL
;
763 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
765 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsEnabled(): no such item") );
767 // int flag = ::GetMenuState(GetHmenuOf(itemMenu), id, MF_BYCOMMAND) ;
769 // don't "and" with MF_ENABLED because its value is 0
770 // return (flag & MF_DISABLED) == 0;
774 void wxMenuBar::SetLabel(int id
, const wxString
& label
)
776 wxMenu
*itemMenu
= NULL
;
777 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
779 wxCHECK_RET( item
, wxT("wxMenuBar::SetLabel(): no such item") );
781 item
->SetName(label
);
784 wxString
wxMenuBar::GetLabel(int id
) const
786 wxMenu
*itemMenu
= NULL
;
787 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
789 wxCHECK_MSG( item
, wxT(""), wxT("wxMenuBar::GetLabel(): no such item") );
791 return item
->GetName();
794 void wxMenuBar::SetHelpString (int id
, const wxString
& helpString
)
796 wxMenu
*itemMenu
= NULL
;
797 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
799 wxCHECK_RET( item
, wxT("wxMenuBar::SetHelpString(): no such item") );
801 item
->SetHelp(helpString
);
804 wxString
wxMenuBar::GetHelpString (int id
) const
806 wxMenu
*itemMenu
= NULL
;
807 wxMenuItem
*item
= FindItemForId(id
, &itemMenu
) ;
809 wxCHECK_MSG( item
, wxT(""), wxT("wxMenuBar::GetHelpString(): no such item") );
811 return item
->GetHelp();
814 // ---------------------------------------------------------------------------
815 // wxMenuBar functions to work with the top level submenus
816 // ---------------------------------------------------------------------------
818 // NB: we don't support owner drawn top level items for now, if we do these
819 // functions would have to be changed to use wxMenuItem as well
821 void wxMenuBar::SetLabelTop(int pos
, const wxString
& label
)
824 UINT flagsOld
= 0; // TODO: ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION);
825 if ( flagsOld
== 0xFFFFFFFF )
827 wxLogLastError(wxT("GetMenuState"));
832 // if ( flagsOld & MF_POPUP )
834 // // HIBYTE contains the number of items in the submenu in this case
835 // flagsOld &= 0xff ;
836 // id = (UINT)::GetSubMenu((HMENU)m_hMenu, pos) ;
843 // if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld,
844 // id, label) == 0xFFFFFFFF )
846 // wxLogLastError("ModifyMenu");
850 wxString
wxMenuBar::GetLabelTop(int pos
) const
852 int len
= 0; // TODO: ::GetMenuString((HMENU)m_hMenu, pos, NULL, 0, MF_BYCOMMAND);
854 len
++; // for the NUL character
856 // ::GetMenuString(GetHmenu(), pos, label.GetWriteBuf(len), len, MF_BYCOMMAND);
857 label
.UngetWriteBuf();
862 // ---------------------------------------------------------------------------
863 // wxMenuBar notifications
864 // ---------------------------------------------------------------------------
866 bool wxMenuBar::OnDelete(wxMenu
*a_menu
, int pos
)
868 if ( !m_menuBarFrame
)
873 if ( ::RemoveMenu((HMENU)m_hMenu, (UINT)pos, MF_BYPOSITION) )
875 // VZ: I'm not sure about what's going on here, so I leave an assert
876 wxASSERT_MSG( m_menus[pos] == a_menu, wxT("what is this parameter for??") );
880 if ( m_menuBarFrame )
887 wxLogLastError("RemoveMenu");
893 bool wxMenuBar::OnAppend(wxMenu
*a_menu
, const wxChar
*title
)
895 WXHMENU submenu
= a_menu
->GetHMenu();
899 if ( !m_menuBarFrame
)
902 a_menu
->Attach(this);
904 // if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
905 // (UINT)submenu, title) )
907 // wxLogLastError(wxT("AppendMenu"));
915 // ---------------------------------------------------------------------------
916 // wxMenuBar construction
917 // ---------------------------------------------------------------------------
918 int wxMenuBar::FindMenu(const wxString
& title
)
920 wxString menuTitle
= wxStripMenuCodes(title
);
921 for ( int i
= 0; i
< m_menuCount
; i
++ )
923 wxString title
= wxStripMenuCodes(m_titles
[i
]);
924 if ( menuTitle
== title
)
933 void wxMenuBar::ReplaceMenu(int pos
, wxMenu
* new_menu
, const wxString
& title
)
935 if (m_menuBarFrame
) return;
937 if ( pos
>= 0 && pos
< m_menuCount
)
939 wxMenu
*old_menu
= m_menus
[pos
];
940 m_menus
[pos
] = new_menu
;
947 void wxMenuBar::Insert(int pos
, wxMenu
* menu
, const wxString
& title
)
949 if (m_menuBarFrame
) return;
950 if ( pos
< 0 && pos
>= m_menuCount
) return;
953 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
954 wxString
*new_titles
= new wxString
[m_menuCount
];
957 for (i
= 0; i
< pos
; i
++)
959 new_menus
[i
] = m_menus
[i
];
961 new_titles
[i
] = m_titles
[i
];
962 m_titles
[i
] = wxT("");
965 new_menus
[pos
] = (wxMenu
*)menu
;
966 new_titles
[i
] = title
;
968 for (i
= pos
+1; i
< m_menuCount
; i
++)
970 new_menus
[i
] = m_menus
[i
-1];
972 new_titles
[i
] = m_titles
[i
-1];
973 m_titles
[i
-1] = wxT("");
981 m_titles
= new_titles
;
983 menu
->SetParent(this);
988 void wxMenuBar::Append (wxMenu
* menu
, const wxString
& title
)
990 if (!OnAppend(menu
, title
))
994 wxMenu
**new_menus
= new wxMenu
*[m_menuCount
];
995 wxString
*new_titles
= new wxString
[m_menuCount
];
998 for (i
= 0; i
< m_menuCount
- 1; i
++)
1000 new_menus
[i
] = m_menus
[i
];
1002 new_titles
[i
] = m_titles
[i
];
1003 m_titles
[i
] = wxT("");
1010 m_menus
= new_menus
;
1011 m_titles
= new_titles
;
1013 m_menus
[m_menuCount
- 1] = (wxMenu
*)menu
;
1014 m_titles
[m_menuCount
- 1] = title
;
1016 menu
->SetParent(this);
1019 void wxMenuBar::Delete(wxMenu
* menu
, int i
)
1025 for (ii
= 0; ii
< m_menuCount
; ii
++) {
1026 if (m_menus
[ii
] == menu
)
1029 if (ii
>= m_menuCount
)
1032 if (ii
< 0 || ii
>= m_menuCount
)
1037 if (!OnDelete(menu
, ii
))
1040 menu
->SetParent(NULL
);
1043 for (j
= ii
; j
< m_menuCount
; j
++) {
1044 m_menus
[j
] = m_menus
[j
+ 1];
1045 m_titles
[j
] = m_titles
[j
+ 1];
1049 void wxMenuBar::Attach(wxFrame
*frame
)
1051 wxASSERT_MSG( !m_menuBarFrame
, wxT("menubar already attached!") );
1053 m_menuBarFrame
= frame
;
1056 // create the accel table - we consider that the menubar construction is
1058 size_t nAccelCount
= 0;
1060 for ( i
= 0; i
< m_menuCount
; i
++ )
1062 nAccelCount
+= m_menus
[i
]->GetAccelCount();
1067 wxAcceleratorEntry
*accelEntries
= new wxAcceleratorEntry
[nAccelCount
];
1070 for ( i
= 0; i
< m_menuCount
; i
++ )
1072 nAccelCount
+= m_menus
[i
]->CopyAccels(&accelEntries
[nAccelCount
]);
1075 m_accelTable
= wxAcceleratorTable(nAccelCount
, accelEntries
);
1077 delete [] accelEntries
;
1079 #endif // wxUSE_ACCEL
1082 void wxMenuBar::Detach()
1084 // ::DestroyMenu((HMENU)m_hMenu);
1086 m_menuBarFrame
= NULL
;
1090 // ---------------------------------------------------------------------------
1091 // wxMenuBar searching for menu items
1092 // ---------------------------------------------------------------------------
1094 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1095 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1096 const wxString
& itemString
) const
1098 wxString menuLabel
= wxStripMenuCodes(menuString
);
1099 for ( int i
= 0; i
< m_menuCount
; i
++ )
1101 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1102 if ( menuString
== title
)
1103 return m_menus
[i
]->FindItem(itemString
);
1109 wxMenuItem
*wxMenuBar::FindItemForId (int id
, wxMenu
**itemMenu
) const
1114 wxMenuItem
*item
= NULL
;
1115 for ( int i
= 0; !item
&& (i
< m_menuCount
); i
++ )
1117 item
= m_menus
[i
]->FindItemForId(id
, itemMenu
);
1124 // ----------------------------------------------------------------------------
1126 // ----------------------------------------------------------------------------
1128 wxWindow
*wxMenu::GetWindow() const
1130 if ( m_pInvokingWindow
!= NULL
)
1131 return m_pInvokingWindow
;
1132 else if ( m_menuBar
!= NULL
)
1133 return m_menuBar
->GetFrame();
1138 WXHMENU
wxMenu::GetHMenu() const
1142 else if ( m_savehMenu
!= 0 )
1145 wxFAIL_MSG(wxT("wxMenu without HMENU"));
1150 // Update a menu and all submenus recursively. source is the object that has
1151 // the update event handlers defined for it. If NULL, the menu or associated
1152 // window will be used.
1153 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1155 if (!source
&& GetInvokingWindow())
1156 source
= GetInvokingWindow()->GetEventHandler();
1158 source
= GetEventHandler();
1162 wxNode
* node
= GetItems().First();
1165 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1166 if ( !item
->IsSeparator() )
1168 wxWindowID id
= item
->GetId();
1169 wxUpdateUIEvent
event(id
);
1170 event
.SetEventObject( source
);
1172 if (source
->ProcessEvent(event
))
1174 if (event
.GetSetText())
1175 SetLabel(id
, event
.GetText());
1176 if (event
.GetSetChecked())
1177 Check(id
, event
.GetChecked());
1178 if (event
.GetSetEnabled())
1179 Enable(id
, event
.GetEnabled());
1182 if (item
->GetSubMenu())
1183 item
->GetSubMenu()->UpdateUI(source
);
1185 node
= node
->Next();