]> git.saurik.com Git - wxWidgets.git/blame - src/os2/menu.cpp
wxBitmap::LoadFile and SaveFile now uses wxImage's methods in case there is no wxBitm...
[wxWidgets.git] / src / os2 / menu.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: menu.cpp
3// Purpose: wxMenu, wxMenuBar, wxMenuItem
75f11ad7 4// Author: David Webster
0e320a79 5// Modified by:
75f11ad7 6// Created: 10/10/99
0e320a79 7// RCS-ID: $Id$
75f11ad7
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
75f11ad7
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
0e320a79 14
75f11ad7
DW
15#ifndef WX_PRECOMP
16 #include "wx/frame.h"
17 #include "wx/menu.h"
18 #include "wx/utils.h"
19 #include "wx/intl.h"
c5fb56c0 20 #include "wx/log.h"
75f11ad7 21#endif
0e320a79 22
75f11ad7
DW
23#if wxUSE_OWNER_DRAWN
24 #include "wx/ownerdrw.h"
0e320a79
DW
25#endif
26
75f11ad7 27#include "wx/os2/private.h"
0e320a79
DW
28
29// other standard headers
0e320a79
DW
30#include <string.h>
31
75f11ad7
DW
32// ----------------------------------------------------------------------------
33// global variables
34// ----------------------------------------------------------------------------
35
36extern wxMenu *wxCurrentPopupMenu;
37
38// ----------------------------------------------------------------------------
39// constants
40// ----------------------------------------------------------------------------
41
42// the (popup) menu title has this special id
43static const int idMenuTitle = -2;
44
45// ----------------------------------------------------------------------------
46// macros
47// ----------------------------------------------------------------------------
48
0e320a79 49#if !USE_SHARED_LIBRARY
75f11ad7
DW
50 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
51 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
0e320a79
DW
52#endif
53
54// ============================================================================
55// implementation
56// ============================================================================
57
75f11ad7
DW
58// ---------------------------------------------------------------------------
59// wxMenu construction, adding and removing menu items
60// ---------------------------------------------------------------------------
0e320a79
DW
61
62// Construct a menu with optional title (then use append)
c5fb56c0 63void wxMenu::Init()
0e320a79 64{
c5fb56c0 65 m_doBreak = FALSE;
75f11ad7 66
c5fb56c0
DW
67 // create the menu
68 m_hMenu = (WXHMENU)0; // CreatePopupMenu();
69 if ( !m_hMenu )
0e320a79 70 {
c5fb56c0 71 wxLogLastError("CreatePopupMenu");
0e320a79
DW
72 }
73
c5fb56c0
DW
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 }
0e320a79
DW
80}
81
82// The wxWindow destructor will take care of deleting the submenus.
83wxMenu::~wxMenu()
84{
c5fb56c0
DW
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() )
75f11ad7 89 {
c5fb56c0
DW
90/*
91 if ( !::DestroyMenu(GetHmenu()) )
92 {
93 wxLogLastError("DestroyMenu");
94 }
95*/
75f11ad7 96 }
0e320a79 97
c5fb56c0
DW
98#if wxUSE_ACCEL
99 // delete accels
100 WX_CLEAR_ARRAY(m_accels);
101#endif // wxUSE_ACCEL
0e320a79
DW
102}
103
104void wxMenu::Break()
105{
c5fb56c0 106 // this will take effect during the next call to Append()
75f11ad7 107 m_doBreak = TRUE;
0e320a79
DW
108}
109
c5fb56c0
DW
110#if wxUSE_ACCEL
111
112int wxMenu::FindAccel(int id) const
0e320a79 113{
c5fb56c0
DW
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 }
75f11ad7 120
c5fb56c0
DW
121 return wxNOT_FOUND;
122}
75f11ad7 123
c5fb56c0
DW
124void 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();
75f11ad7 130
c5fb56c0
DW
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);
75f11ad7 149 }
c5fb56c0
DW
150
151 if ( IsAttached() )
152 {
153 m_menuBar->RebuildAccelTable();
154 }
155}
156
75f11ad7 157#endif // wxUSE_ACCEL
0e320a79 158
c5fb56c0
DW
159// append a new item or submenu to the menu
160bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
161{
162#if wxUSE_ACCEL
163 UpdateAccel(pItem);
164#endif // wxUSE_ACCEL
0e320a79 165
c5fb56c0
DW
166 UINT flags = 0;
167// TODO:
75f11ad7
DW
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 }
0e320a79 175
75f11ad7
DW
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 ) {
c5fb56c0
DW
185 wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );
186
187 submenu->SetParent(this);
75f11ad7
DW
188
189 id = (UINT)submenu->GetHMenu();
75f11ad7
DW
190
191 flags |= MF_POPUP;
192 }
193 else {
194 id = pItem->GetId();
195 }
196
c5fb56c0 197 LPCTSTR pData;
75f11ad7
DW
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;
c5fb56c0 203 pData = (LPCTSTR)pItem;
75f11ad7
DW
204 }
205 else
206#endif
207 {
208 // menu is just a normal string (passed in data parameter)
209 flags |= MF_STRING;
c5fb56c0
DW
210
211 pData = (char*)pItem->GetText().c_str();
75f11ad7 212 }
c5fb56c0
DW
213
214 BOOL ok;
215 if ( pos == (size_t)-1 )
75f11ad7 216 {
c5fb56c0 217 ok = ::AppendMenu(GetHmenu(), flags, id, pData);
75f11ad7
DW
218 }
219 else
220 {
c5fb56c0
DW
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 )
75f11ad7
DW
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 }
c5fb56c0
DW
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;
75f11ad7
DW
256 }
257*/
c5fb56c0 258 return FALSE;
0e320a79
DW
259}
260
c5fb56c0 261bool wxMenu::DoAppend(wxMenuItem *item)
0e320a79 262{
c5fb56c0 263 return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
0e320a79
DW
264}
265
c5fb56c0 266bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
0e320a79 267{
c5fb56c0 268 return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
0e320a79
DW
269}
270
c5fb56c0 271wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
0e320a79 272{
c5fb56c0
DW
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++ )
75f11ad7 277 {
c5fb56c0 278 if ( node->GetData() == item )
75f11ad7 279 break;
c5fb56c0
DW
280
281 node = node->GetNext();
0e320a79
DW
282 }
283
c5fb56c0
DW
284 // DoRemove() (unlike Remove) can only be called for existing item!
285 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
75f11ad7 286
c5fb56c0
DW
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];
75f11ad7 293
c5fb56c0
DW
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) )
75f11ad7 301 {
c5fb56c0
DW
302 wxLogLastError("RemoveMenu");
303 }
304*/
305 if ( IsAttached() )
306 {
307 // otherwise, the chane won't be visible
308 m_menuBar->Refresh();
75f11ad7 309 }
0e320a79 310
c5fb56c0
DW
311 // and from internal data structures
312 return wxMenuBase::DoRemove(item);
75f11ad7 313}
0e320a79 314
75f11ad7
DW
315// ---------------------------------------------------------------------------
316// accelerator helpers
317// ---------------------------------------------------------------------------
318
c5fb56c0
DW
319#if wxUSE_ACCEL
320
75f11ad7
DW
321// create the wxAcceleratorEntries for our accels and put them into provided
322// array - return the number of accels we have
323size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
324{
325 size_t count = GetAccelCount();
326 for ( size_t n = 0; n < count; n++ )
327 {
c5fb56c0 328 *accels++ = *m_accels[n];
75f11ad7
DW
329 }
330
331 return count;
0e320a79
DW
332}
333
75f11ad7
DW
334#endif // wxUSE_ACCEL
335
336// ---------------------------------------------------------------------------
c5fb56c0 337// set wxMenu title
75f11ad7
DW
338// ---------------------------------------------------------------------------
339
340void wxMenu::SetTitle(const wxString& label)
0e320a79 341{
75f11ad7
DW
342 bool hasNoTitle = m_title.IsEmpty();
343 m_title = label;
0e320a79 344
75f11ad7 345 HMENU hMenu = GetHmenu();
c5fb56c0 346
75f11ad7 347 if ( hasNoTitle )
0e320a79 348 {
75f11ad7
DW
349 if ( !label.IsEmpty() )
350 {
c5fb56c0
DW
351/*
352 if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
353 (unsigned)idMenuTitle, m_title) ||
354 !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
75f11ad7 355 {
c5fb56c0 356 wxLogLastError("InsertMenu");
75f11ad7 357 }
c5fb56c0 358*/
75f11ad7 359 }
0e320a79 360 }
75f11ad7 361 else
0e320a79 362 {
75f11ad7 363 if ( label.IsEmpty() )
0e320a79 364 {
c5fb56c0 365/*
75f11ad7
DW
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 }
c5fb56c0 372*/
0e320a79 373 }
75f11ad7 374 else
0e320a79 375 {
c5fb56c0 376/*
75f11ad7
DW
377 // modify the title
378 if ( !ModifyMenu(hMenu, 0u,
c5fb56c0
DW
379 MF_BYPOSITION | MF_STRING,
380 (unsigned)idMenuTitle, m_title) )
75f11ad7
DW
381 {
382 wxLogLastError("ModifyMenu");
383 }
c5fb56c0 384*/
0e320a79
DW
385 }
386 }
c5fb56c0
DW
387/*
388#ifdef __WIN32__
75f11ad7
DW
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 }
c5fb56c0 402#endif // Win32
75f11ad7 403*/
0e320a79
DW
404}
405
75f11ad7
DW
406// ---------------------------------------------------------------------------
407// event processing
408// ---------------------------------------------------------------------------
409
410bool wxMenu::OS2Command(WXUINT WXUNUSED(param), WXWORD id)
0e320a79 411{
75f11ad7
DW
412 // ignore commands from the menu title
413
c5fb56c0 414 // NB: VC++ generates wrong assembler for `if ( id != idMenuTitle )'!!
75f11ad7
DW
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;
0e320a79
DW
425}
426
75f11ad7 427bool wxMenu::ProcessCommand(wxCommandEvent & event)
0e320a79
DW
428{
429 bool processed = FALSE;
430
c5fb56c0 431#if WXWIN_COMPATIBILITY
0e320a79
DW
432 // Try a callback
433 if (m_callback)
434 {
75f11ad7
DW
435 (void)(*(m_callback))(*this, event);
436 processed = TRUE;
0e320a79 437 }
c5fb56c0 438#endif // WXWIN_COMPATIBILITY
0e320a79
DW
439
440 // Try the menu's event handler
441 if ( !processed && GetEventHandler())
442 {
75f11ad7 443 processed = GetEventHandler()->ProcessEvent(event);
0e320a79 444 }
75f11ad7
DW
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;
0e320a79
DW
453}
454
75f11ad7
DW
455// ---------------------------------------------------------------------------
456// other
457// ---------------------------------------------------------------------------
458
459void wxMenu::Attach(wxMenuBar *menubar)
0e320a79 460{
75f11ad7
DW
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") );
0e320a79 464
75f11ad7 465 m_menuBar = menubar;
75f11ad7
DW
466}
467
468void wxMenu::Detach()
469{
470 wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
471
c5fb56c0
DW
472 m_menuBar = NULL;
473}
474
475wxWindow *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;
0e320a79
DW
483}
484
75f11ad7 485// ---------------------------------------------------------------------------
0e320a79 486// Menu Bar
75f11ad7
DW
487// ---------------------------------------------------------------------------
488
489void wxMenuBar::Init()
0e320a79
DW
490{
491 m_eventHandler = this;
0e320a79 492 m_menuBarFrame = NULL;
75f11ad7
DW
493 m_hMenu = 0;
494}
0e320a79 495
75f11ad7
DW
496wxMenuBar::wxMenuBar()
497{
498 Init();
0e320a79
DW
499}
500
75f11ad7 501wxMenuBar::wxMenuBar( long WXUNUSED(style) )
0e320a79 502{
75f11ad7
DW
503 Init();
504}
505
506wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
507{
508 Init();
509
c5fb56c0 510 m_titles.Alloc(count);
75f11ad7 511
c5fb56c0
DW
512 for ( int i = 0; i < count; i++ )
513 {
514 m_menus.Append(menus[i]);
515 m_titles.Add(titles[i]);
0e320a79 516
c5fb56c0
DW
517 menus[i]->Attach(this);
518 }
0e320a79
DW
519}
520
521wxMenuBar::~wxMenuBar()
522{
75f11ad7 523}
0e320a79 524
75f11ad7
DW
525// ---------------------------------------------------------------------------
526// wxMenuBar helpers
527// ---------------------------------------------------------------------------
528
c5fb56c0
DW
529void wxMenuBar::Refresh(
530 bool WXUNUSED(bEraseBackground)
531, const wxRect* WXUNUSED(pRect)
532)
75f11ad7 533{
c5fb56c0 534 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
75f11ad7 535
c5fb56c0 536// DrawMenuBar(GetHwndOf(m_menuBarFrame));
75f11ad7
DW
537}
538
539WXHMENU wxMenuBar::Create()
540{
541 if (m_hMenu != 0 )
c5fb56c0 542 return m_hMenu;
75f11ad7
DW
543
544 wxCHECK_MSG( !m_hMenu, TRUE, wxT("menubar already created") );
545
c5fb56c0
DW
546// TODO:
547/*
548
549 m_hMenu = (WXHMENU)::CreateMenu();
75f11ad7
DW
550
551 if ( !m_hMenu )
552 {
553 wxLogLastError("CreateMenu");
554 }
555 else
556 {
c5fb56c0
DW
557 size_t count = GetMenuCount();
558 for ( size_t i = 0; i < count; i++ )
75f11ad7 559 {
c5fb56c0
DW
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 }
75f11ad7
DW
566 }
567 }
568
569 return m_hMenu;
c5fb56c0
DW
570*/
571 return (WXHMENU)0;
0e320a79
DW
572}
573
75f11ad7 574// ---------------------------------------------------------------------------
c5fb56c0 575// wxMenuBar functions to work with the top level submenus
75f11ad7
DW
576// ---------------------------------------------------------------------------
577
c5fb56c0
DW
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
0e320a79 580
c5fb56c0 581void wxMenuBar::EnableTop(size_t pos, bool enable)
0e320a79 582{
c5fb56c0 583 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
0e320a79 584
c5fb56c0 585// int flag = enable ? MF_ENABLED : MF_GRAYED;
75f11ad7 586
c5fb56c0 587// EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag);
75f11ad7 588
c5fb56c0 589 Refresh();
75f11ad7
DW
590}
591
c5fb56c0 592void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
75f11ad7 593{
c5fb56c0 594 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
75f11ad7 595
c5fb56c0 596 m_titles[pos] = label;
75f11ad7 597
c5fb56c0
DW
598 if ( !IsAttached() )
599 {
600 return;
601 }
602 //else: have to modify the existing menu
75f11ad7 603
c5fb56c0
DW
604// TODO:
605/*
75f11ad7 606 UINT id;
c5fb56c0 607 UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION);
75f11ad7
DW
608 if ( flagsOld == 0xFFFFFFFF )
609 {
610 wxLogLastError(wxT("GetMenuState"));
611
612 return;
613 }
614
c5fb56c0 615 if ( flagsOld & MF_POPUP )
75f11ad7 616 {
c5fb56c0
DW
617 // HIBYTE contains the number of items in the submenu in this case
618 flagsOld &= 0xff;
619 id = (UINT)::GetSubMenu((HMENU)m_hMenu, pos);
75f11ad7
DW
620 }
621 else
622 {
c5fb56c0
DW
623 id = pos;
624 }
625
626 if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld,
627 id, label) == (int)0xFFFFFFFF )
628 {
629 wxLogLastError("ModifyMenu");
75f11ad7
DW
630 }
631*/
c5fb56c0 632 Refresh();
0e320a79
DW
633}
634
c5fb56c0 635wxString wxMenuBar::GetLabelTop(size_t pos) const
0e320a79 636{
c5fb56c0
DW
637 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
638 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
75f11ad7 639
c5fb56c0 640 return m_titles[pos];
0e320a79
DW
641}
642
75f11ad7
DW
643int wxMenuBar::FindMenu(const wxString& title)
644{
645 wxString menuTitle = wxStripMenuCodes(title);
c5fb56c0
DW
646
647 size_t count = GetMenuCount();
648 for ( size_t i = 0; i < count; i++ )
75f11ad7
DW
649 {
650 wxString title = wxStripMenuCodes(m_titles[i]);
651 if ( menuTitle == title )
652 return i;
653 }
654
655 return wxNOT_FOUND;
656
657}
658
c5fb56c0
DW
659// ---------------------------------------------------------------------------
660// wxMenuBar construction
661// ---------------------------------------------------------------------------
75f11ad7 662
c5fb56c0 663wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
75f11ad7 664{
c5fb56c0
DW
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() )
75f11ad7 672 {
c5fb56c0
DW
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 }
75f11ad7 678
c5fb56c0
DW
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
75f11ad7 693
c5fb56c0
DW
694 Refresh();
695 }
696*/
697 return menuOld;
698}
75f11ad7 699
c5fb56c0 700bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
75f11ad7 701{
c5fb56c0
DW
702 if ( !wxMenuBarBase::Insert(pos, menu, title) )
703 return FALSE;
75f11ad7 704
c5fb56c0 705 m_titles.Insert(title, pos);
75f11ad7 706
c5fb56c0
DW
707 menu->Attach(this);
708// TODO:
709/*
710 if ( IsAttached() )
75f11ad7 711 {
c5fb56c0
DW
712 if ( !::InsertMenu(GetHmenu(), pos,
713 MF_BYPOSITION | MF_POPUP | MF_STRING,
714 (UINT)GetHmenuOf(menu), title) )
715 {
716 wxLogLastError("InsertMenu");
717 }
75f11ad7 718
c5fb56c0
DW
719#if wxUSE_ACCEL
720 if ( menu->HasAccels() )
721 {
722 // need to rebuild accell table
723 RebuildAccelTable();
724 }
725#endif // wxUSE_ACCEL
75f11ad7 726
c5fb56c0 727 Refresh();
75f11ad7 728 }
c5fb56c0
DW
729*/
730 return TRUE;
75f11ad7
DW
731}
732
c5fb56c0 733bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
0e320a79 734{
c5fb56c0
DW
735 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
736 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
0e320a79 737
c5fb56c0
DW
738 if ( !wxMenuBarBase::Append(menu, title) )
739 return FALSE;
0e320a79 740
c5fb56c0
DW
741 menu->Attach(this);
742
743 m_titles.Add(title);
744// TODO:
745/*
746 if ( IsAttached() )
0e320a79 747 {
c5fb56c0
DW
748 if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
749 (UINT)submenu, title) )
750 {
751 wxLogLastError(wxT("AppendMenu"));
752 }
0e320a79 753
c5fb56c0
DW
754#if wxUSE_ACCEL
755 if ( menu->HasAccels() )
756 {
757 // need to rebuild accell table
758 RebuildAccelTable();
759 }
760#endif // wxUSE_ACCEL
0e320a79 761
c5fb56c0
DW
762 Refresh();
763 }
764*/
765 return TRUE;
0e320a79
DW
766}
767
c5fb56c0 768wxMenu *wxMenuBar::Remove(size_t pos)
0e320a79 769{
c5fb56c0
DW
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");
75f11ad7 780 }
0e320a79 781
c5fb56c0 782 menu->Detach();
0e320a79 783
c5fb56c0
DW
784#if wxUSE_ACCEL
785 if ( menu->HasAccels() )
786 {
787 // need to rebuild accell table
788 RebuildAccelTable();
789 }
790#endif // wxUSE_ACCEL
0e320a79 791
c5fb56c0 792 Refresh();
0e320a79 793 }
75f11ad7 794
c5fb56c0
DW
795 m_titles.Remove(pos);
796*/
797 return menu;
798}
75f11ad7
DW
799
800#if wxUSE_ACCEL
c5fb56c0
DW
801
802void wxMenuBar::RebuildAccelTable()
803{
804 // merge the accelerators of all menus into one accel table
75f11ad7 805 size_t nAccelCount = 0;
c5fb56c0
DW
806 size_t i, count = GetMenuCount();
807 for ( i = 0; i < count; i++ )
75f11ad7
DW
808 {
809 nAccelCount += m_menus[i]->GetAccelCount();
810 }
811
812 if ( nAccelCount )
0e320a79 813 {
75f11ad7
DW
814 wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount];
815
816 nAccelCount = 0;
c5fb56c0 817 for ( i = 0; i < count; i++ )
75f11ad7
DW
818 {
819 nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]);
820 }
821
822 m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries);
823
824 delete [] accelEntries;
0e320a79 825 }
c5fb56c0
DW
826}
827
828#endif // wxUSE_ACCEL
829
830void 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();
75f11ad7 838#endif // wxUSE_ACCEL
0e320a79
DW
839}
840
75f11ad7 841void wxMenuBar::Detach()
0e320a79 842{
75f11ad7 843// ::DestroyMenu((HMENU)m_hMenu);
c5fb56c0 844 m_hMenu = (WXHMENU)NULL;
75f11ad7
DW
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
854int wxMenuBar::FindMenuItem(const wxString& menuString,
855 const wxString& itemString) const
856{
857 wxString menuLabel = wxStripMenuCodes(menuString);
c5fb56c0
DW
858 size_t count = GetMenuCount();
859 for ( size_t i = 0; i < count; i++ )
75f11ad7
DW
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
c5fb56c0 869wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
75f11ad7
DW
870{
871 if ( itemMenu )
0e320a79
DW
872 *itemMenu = NULL;
873
874 wxMenuItem *item = NULL;
c5fb56c0
DW
875 size_t count = GetMenuCount();
876 for ( size_t i = 0; !item && (i < count); i++ )
75f11ad7 877 {
c5fb56c0 878 item = m_menus[i]->FindItem(id, itemMenu);
75f11ad7
DW
879 }
880
881 return item;
882}
883