~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Externals/wxWidgets3/src/common/menucmn.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/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
// Copyright:   (c) wxWidgets team
 
8
// Licence:     wxWindows licence
 
9
///////////////////////////////////////////////////////////////////////////////
 
10
 
 
11
// ============================================================================
 
12
// declarations
 
13
// ============================================================================
 
14
 
 
15
// ----------------------------------------------------------------------------
 
16
// headers
 
17
// ----------------------------------------------------------------------------
 
18
 
 
19
// For compilers that support precompilation, includes "wx.h".
 
20
#include "wx/wxprec.h"
 
21
 
 
22
#ifdef __BORLANDC__
 
23
    #pragma hdrstop
 
24
#endif
 
25
 
 
26
#if wxUSE_MENUS
 
27
 
 
28
#ifndef WX_PRECOMP
 
29
    #include "wx/intl.h"
 
30
    #include "wx/log.h"
 
31
    #include "wx/menu.h"
 
32
    #include "wx/frame.h"
 
33
#endif
 
34
 
 
35
#include "wx/stockitem.h"
 
36
 
 
37
// ----------------------------------------------------------------------------
 
38
// template lists
 
39
// ----------------------------------------------------------------------------
 
40
 
 
41
#include "wx/listimpl.cpp"
 
42
 
 
43
WX_DEFINE_LIST(wxMenuList)
 
44
WX_DEFINE_LIST(wxMenuItemList)
 
45
 
 
46
// ============================================================================
 
47
// implementation
 
48
// ============================================================================
 
49
 
 
50
// ----------------------------------------------------------------------------
 
51
// XTI for wxMenu(Bar)
 
52
// ----------------------------------------------------------------------------
 
53
 
 
54
wxDEFINE_FLAGS( wxMenuStyle )
 
55
wxBEGIN_FLAGS( wxMenuStyle )
 
56
wxFLAGS_MEMBER(wxMENU_TEAROFF)
 
57
wxEND_FLAGS( wxMenuStyle )
 
58
 
 
59
wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxMenu, wxEvtHandler, "wx/menu.h")
 
60
wxCOLLECTION_TYPE_INFO( wxMenuItem *, wxMenuItemList ) ;
 
61
 
 
62
#if wxUSE_EXTENDED_RTTI    
 
63
template<> void wxCollectionToVariantArray( wxMenuItemList const &theList,
 
64
                                           wxAnyList &value)
 
65
{
 
66
    wxListCollectionToAnyList<wxMenuItemList::compatibility_iterator>( theList, value ) ;
 
67
}
 
68
#endif
 
69
 
 
70
wxBEGIN_PROPERTIES_TABLE(wxMenu)
 
71
wxEVENT_PROPERTY( Select, wxEVT_MENU, wxCommandEvent)
 
72
 
 
73
wxPROPERTY( Title, wxString, SetTitle, GetTitle, wxString(), \
 
74
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
75
 
 
76
wxREADONLY_PROPERTY_FLAGS( MenuStyle, wxMenuStyle, long, GetStyle, \
 
77
                          wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, wxT("Helpstring"), \
 
78
                          wxT("group")) // style
 
79
 
 
80
wxPROPERTY_COLLECTION( MenuItems, wxMenuItemList, wxMenuItem*, Append, \
 
81
                      GetMenuItems, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
 
82
wxEND_PROPERTIES_TABLE()
 
83
 
 
84
wxEMPTY_HANDLERS_TABLE(wxMenu)
 
85
 
 
86
wxDIRECT_CONSTRUCTOR_2( wxMenu, wxString, Title, long, MenuStyle  )
 
87
 
 
88
wxDEFINE_FLAGS( wxMenuBarStyle )
 
89
 
 
90
wxBEGIN_FLAGS( wxMenuBarStyle )
 
91
wxFLAGS_MEMBER(wxMB_DOCKABLE)
 
92
wxEND_FLAGS( wxMenuBarStyle )
 
93
 
 
94
#if wxUSE_EXTENDED_RTTI    
 
95
// the negative id would lead the window (its superclass !) to
 
96
// vetoe streaming out otherwise
 
97
bool wxMenuBarStreamingCallback( const wxObject *WXUNUSED(object), wxObjectWriter *,
 
98
                                wxObjectWriterCallback *, const wxStringToAnyHashMap & )
 
99
{
 
100
    return true;
 
101
}
 
102
#endif
 
103
 
 
104
wxIMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuBar, wxWindow, "wx/menu.h", \
 
105
                                       wxMenuBarStreamingCallback)
 
106
 
 
107
 
 
108
#if wxUSE_EXTENDED_RTTI    
 
109
WX_DEFINE_LIST( wxMenuInfoHelperList )
 
110
 
 
111
wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxMenuInfoHelper, wxObject, "wx/menu.h")
 
112
 
 
113
wxBEGIN_PROPERTIES_TABLE(wxMenuInfoHelper)
 
114
wxREADONLY_PROPERTY( Menu, wxMenu*, GetMenu, wxEMPTY_PARAMETER_VALUE, \
 
115
                    0 /*flags*/, wxT("Helpstring"), wxT("group"))
 
116
 
 
117
wxREADONLY_PROPERTY( Title, wxString, GetTitle, wxString(), \
 
118
                    0 /*flags*/, wxT("Helpstring"), wxT("group"))
 
119
wxEND_PROPERTIES_TABLE()
 
120
 
 
121
wxEMPTY_HANDLERS_TABLE(wxMenuInfoHelper)
 
122
 
 
123
wxCONSTRUCTOR_2( wxMenuInfoHelper, wxMenu*, Menu, wxString, Title )
 
124
 
 
125
wxCOLLECTION_TYPE_INFO( wxMenuInfoHelper *, wxMenuInfoHelperList ) ;
 
126
 
 
127
template<> void wxCollectionToVariantArray( wxMenuInfoHelperList const &theList, 
 
128
                                           wxAnyList &value)
 
129
{
 
130
    wxListCollectionToAnyList<wxMenuInfoHelperList::compatibility_iterator>( theList, value ) ;
 
131
}
 
132
 
 
133
#endif
 
134
 
 
135
wxBEGIN_PROPERTIES_TABLE(wxMenuBar)
 
136
wxPROPERTY_COLLECTION( MenuInfos, wxMenuInfoHelperList, wxMenuInfoHelper*, AppendMenuInfo, \
 
137
                      GetMenuInfos, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
 
138
wxEND_PROPERTIES_TABLE()
 
139
 
 
140
wxEMPTY_HANDLERS_TABLE(wxMenuBar)
 
141
 
 
142
wxCONSTRUCTOR_DUMMY( wxMenuBar )
 
143
 
 
144
#if wxUSE_EXTENDED_RTTI    
 
145
 
 
146
const wxMenuInfoHelperList& wxMenuBarBase::GetMenuInfos() const
 
147
{
 
148
    wxMenuInfoHelperList* list = const_cast< wxMenuInfoHelperList* > (& m_menuInfos);
 
149
    WX_CLEAR_LIST( wxMenuInfoHelperList, *list);
 
150
    for (size_t i = 0 ; i < GetMenuCount(); ++i)
 
151
    {
 
152
        wxMenuInfoHelper* info = new wxMenuInfoHelper();
 
153
        info->Create( GetMenu(i), GetMenuLabel(i));
 
154
        list->Append(info);
 
155
    }
 
156
    return m_menuInfos;
 
157
}
 
158
 
 
159
#endif
 
160
 
 
161
// ----------------------------------------------------------------------------
 
162
// XTI for wxMenuItem
 
163
// ----------------------------------------------------------------------------
 
164
 
 
165
#if wxUSE_EXTENDED_RTTI
 
166
 
 
167
bool wxMenuItemStreamingCallback( const wxObject *object, wxObjectWriter *,
 
168
                                 wxObjectWriterCallback *, const wxStringToAnyHashMap & )
 
169
{
 
170
    const wxMenuItem * mitem = wx_dynamic_cast(const wxMenuItem*, object);
 
171
    if ( mitem->GetMenu() && !mitem->GetMenu()->GetTitle().empty() )
 
172
    {
 
173
        // we don't stream out the first two items for menus with a title,
 
174
        // they will be reconstructed
 
175
        if ( mitem->GetMenu()->FindItemByPosition(0) == mitem ||
 
176
            mitem->GetMenu()->FindItemByPosition(1) == mitem )
 
177
            return false;
 
178
    }
 
179
    return true;
 
180
}
 
181
 
 
182
#endif
 
183
 
 
184
wxBEGIN_ENUM( wxItemKind )
 
185
wxENUM_MEMBER( wxITEM_SEPARATOR )
 
186
wxENUM_MEMBER( wxITEM_NORMAL )
 
187
wxENUM_MEMBER( wxITEM_CHECK )
 
188
wxENUM_MEMBER( wxITEM_RADIO )
 
189
wxEND_ENUM( wxItemKind )
 
190
 
 
191
wxIMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuItem, wxObject, "wx/menuitem.h", \
 
192
                                       wxMenuItemStreamingCallback)
 
193
 
 
194
wxBEGIN_PROPERTIES_TABLE(wxMenuItem)
 
195
wxPROPERTY( Parent, wxMenu*, SetMenu, GetMenu, wxEMPTY_PARAMETER_VALUE, \
 
196
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
197
wxPROPERTY( Id, int, SetId, GetId, wxEMPTY_PARAMETER_VALUE, \
 
198
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
199
wxPROPERTY( ItemLabel, wxString, SetItemLabel, GetItemLabel, wxString(), \
 
200
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
201
wxPROPERTY( Help, wxString, SetHelp, GetHelp, wxString(), \
 
202
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
203
wxREADONLY_PROPERTY( Kind, wxItemKind, GetKind, wxEMPTY_PARAMETER_VALUE, \
 
204
                    0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
205
wxPROPERTY( SubMenu, wxMenu*, SetSubMenu, GetSubMenu, wxEMPTY_PARAMETER_VALUE, \
 
206
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
207
wxPROPERTY( Enabled, bool, Enable, IsEnabled, wxAny((bool)true), \
 
208
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
209
wxPROPERTY( Checked, bool, Check, IsChecked, wxAny((bool)false), \
 
210
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
211
wxPROPERTY( Checkable, bool, SetCheckable, IsCheckable, wxAny((bool)false), \
 
212
           0 /*flags*/, wxT("Helpstring"), wxT("group") )
 
213
wxEND_PROPERTIES_TABLE()
 
214
 
 
215
wxEMPTY_HANDLERS_TABLE(wxMenuItem)
 
216
 
 
217
wxDIRECT_CONSTRUCTOR_6( wxMenuItem, wxMenu*, Parent, int, Id, wxString, \
 
218
                       Text, wxString, Help, wxItemKind, Kind, wxMenu*, SubMenu )
 
219
 
 
220
// ----------------------------------------------------------------------------
 
221
// wxMenuItemBase
 
222
// ----------------------------------------------------------------------------
 
223
 
 
224
wxMenuItemBase::wxMenuItemBase(wxMenu *parentMenu,
 
225
                               int itemid,
 
226
                               const wxString& text,
 
227
                               const wxString& help,
 
228
                               wxItemKind kind,
 
229
                               wxMenu *subMenu)
 
230
{
 
231
    switch ( itemid )
 
232
    {
 
233
        case wxID_ANY:
 
234
            m_id = wxWindow::NewControlId();
 
235
            break;
 
236
 
 
237
        case wxID_SEPARATOR:
 
238
            m_id = wxID_SEPARATOR;
 
239
 
 
240
            // there is a lot of existing code just doing Append(wxID_SEPARATOR)
 
241
            // and it makes sense to omit the following optional parameters,
 
242
            // including the kind one which doesn't default to wxITEM_SEPARATOR,
 
243
            // of course, so override it here
 
244
            kind = wxITEM_SEPARATOR;
 
245
            break;
 
246
 
 
247
        case wxID_NONE:
 
248
            // (popup) menu titles in wxMSW use this ID to indicate that
 
249
            // it's not a real menu item, so we don't want the check below to
 
250
            // apply to it
 
251
            m_id = itemid;
 
252
            break;
 
253
 
 
254
        default:
 
255
            // ids are limited to 16 bits under MSW so portable code shouldn't
 
256
            // use ids outside of this range (negative ids generated by wx are
 
257
            // fine though)
 
258
            wxASSERT_MSG( (itemid >= 0 && itemid < SHRT_MAX) ||
 
259
                            (itemid >= wxID_AUTO_LOWEST && itemid <= wxID_AUTO_HIGHEST),
 
260
                          wxS("invalid itemid value") );
 
261
            m_id = itemid;
 
262
    }
 
263
 
 
264
    // notice that parentMenu can be NULL: the item can be attached to the menu
 
265
    // later with SetMenu()
 
266
 
 
267
    m_parentMenu  = parentMenu;
 
268
    m_subMenu     = subMenu;
 
269
    m_isEnabled   = true;
 
270
    m_isChecked   = false;
 
271
    m_kind        = kind;
 
272
 
 
273
    SetItemLabel(text);
 
274
    SetHelp(help);
 
275
}
 
276
 
 
277
wxMenuItemBase::~wxMenuItemBase()
 
278
{
 
279
    delete m_subMenu;
 
280
}
 
281
 
 
282
#if wxUSE_ACCEL
 
283
 
 
284
wxAcceleratorEntry *wxMenuItemBase::GetAccel() const
 
285
{
 
286
    return wxAcceleratorEntry::Create(GetItemLabel());
 
287
}
 
288
 
 
289
void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
 
290
{
 
291
    wxString text = m_text.BeforeFirst(wxT('\t'));
 
292
    if ( accel )
 
293
    {
 
294
        text += wxT('\t');
 
295
        text += accel->ToString();
 
296
    }
 
297
 
 
298
    SetItemLabel(text);
 
299
}
 
300
 
 
301
#endif // wxUSE_ACCEL
 
302
 
 
303
void wxMenuItemBase::SetItemLabel(const wxString& str)
 
304
{
 
305
    m_text = str;
 
306
 
 
307
    if ( m_text.empty() && !IsSeparator() )
 
308
    {
 
309
        wxASSERT_MSG( wxIsStockID(GetId()),
 
310
                      wxT("A non-stock menu item with an empty label?") );
 
311
        m_text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR |
 
312
                                          wxSTOCK_WITH_MNEMONIC);
 
313
    }
 
314
}
 
315
 
 
316
void wxMenuItemBase::SetHelp(const wxString& str)
 
317
{
 
318
    m_help = str;
 
319
 
 
320
    if ( m_help.empty() && !IsSeparator() && wxIsStockID(GetId()) )
 
321
    {
 
322
        // get a stock help string
 
323
        m_help = wxGetStockHelpString(GetId());
 
324
    }
 
325
}
 
326
 
 
327
#ifndef __WXPM__
 
328
wxString wxMenuItemBase::GetLabelText(const wxString& text)
 
329
{
 
330
    return wxStripMenuCodes(text);
 
331
}
 
332
#endif
 
333
 
 
334
#if WXWIN_COMPATIBILITY_2_8
 
335
wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
 
336
{
 
337
    return GetLabelText(text);
 
338
}
 
339
#endif
 
340
 
 
341
bool wxMenuBase::ms_locked = true;
 
342
 
 
343
// ----------------------------------------------------------------------------
 
344
// wxMenu ctor and dtor
 
345
// ----------------------------------------------------------------------------
 
346
 
 
347
void wxMenuBase::Init(long style)
 
348
{
 
349
    m_menuBar = NULL;
 
350
    m_menuParent = NULL;
 
351
 
 
352
    m_invokingWindow = NULL;
 
353
    m_style = style;
 
354
    m_clientData = NULL;
 
355
    m_eventHandler = this;
 
356
}
 
357
 
 
358
wxMenuBase::~wxMenuBase()
 
359
{
 
360
    WX_CLEAR_LIST(wxMenuItemList, m_items);
 
361
}
 
362
 
 
363
// ----------------------------------------------------------------------------
 
364
// wxMenu item adding/removing
 
365
// ----------------------------------------------------------------------------
 
366
 
 
367
void wxMenuBase::AddSubMenu(wxMenu *submenu)
 
368
{
 
369
    wxCHECK_RET( submenu, wxT("can't add a NULL submenu") );
 
370
 
 
371
    submenu->SetParent((wxMenu *)this);
 
372
}
 
373
 
 
374
wxMenuItem* wxMenuBase::DoAppend(wxMenuItem *item)
 
375
{
 
376
    wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Append()") );
 
377
 
 
378
    m_items.Append(item);
 
379
    item->SetMenu((wxMenu*)this);
 
380
    if ( item->IsSubMenu() )
 
381
    {
 
382
        AddSubMenu(item->GetSubMenu());
 
383
    }
 
384
 
 
385
    return item;
 
386
}
 
387
 
 
388
wxMenuItem* wxMenuBase::Insert(size_t pos, wxMenuItem *item)
 
389
{
 
390
    wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Insert") );
 
391
 
 
392
    if ( pos == GetMenuItemCount() )
 
393
    {
 
394
        return DoAppend(item);
 
395
    }
 
396
    else
 
397
    {
 
398
        wxCHECK_MSG( pos < GetMenuItemCount(), NULL,
 
399
                     wxT("invalid index in wxMenu::Insert") );
 
400
 
 
401
        return DoInsert(pos, item);
 
402
    }
 
403
}
 
404
 
 
405
wxMenuItem* wxMenuBase::DoInsert(size_t pos, wxMenuItem *item)
 
406
{
 
407
    wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Insert()") );
 
408
 
 
409
    wxMenuItemList::compatibility_iterator node = m_items.Item(pos);
 
410
    wxCHECK_MSG( node, NULL, wxT("invalid index in wxMenu::Insert()") );
 
411
 
 
412
    m_items.Insert(node, item);
 
413
    item->SetMenu((wxMenu*)this);
 
414
    if ( item->IsSubMenu() )
 
415
    {
 
416
        AddSubMenu(item->GetSubMenu());
 
417
    }
 
418
 
 
419
    return item;
 
420
}
 
421
 
 
422
wxMenuItem *wxMenuBase::Remove(wxMenuItem *item)
 
423
{
 
424
    wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Remove") );
 
425
 
 
426
    return DoRemove(item);
 
427
}
 
428
 
 
429
wxMenuItem *wxMenuBase::DoRemove(wxMenuItem *item)
 
430
{
 
431
    wxMenuItemList::compatibility_iterator node = m_items.Find(item);
 
432
 
 
433
    // if we get here, the item is valid or one of Remove() functions is broken
 
434
    wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
 
435
 
 
436
    // we detach the item, but we do delete the list node (i.e. don't call
 
437
    // DetachNode() here!)
 
438
    m_items.Erase(node);
 
439
 
 
440
    // item isn't attached to anything any more
 
441
    item->SetMenu(NULL);
 
442
    wxMenu *submenu = item->GetSubMenu();
 
443
    if ( submenu )
 
444
    {
 
445
        submenu->SetParent(NULL);
 
446
        if ( submenu->IsAttached() )
 
447
            submenu->Detach();
 
448
    }
 
449
 
 
450
    return item;
 
451
}
 
452
 
 
453
bool wxMenuBase::Delete(wxMenuItem *item)
 
454
{
 
455
    wxCHECK_MSG( item, false, wxT("invalid item in wxMenu::Delete") );
 
456
 
 
457
    return DoDelete(item);
 
458
}
 
459
 
 
460
bool wxMenuBase::DoDelete(wxMenuItem *item)
 
461
{
 
462
    wxMenuItem *item2 = DoRemove(item);
 
463
    wxCHECK_MSG( item2, false, wxT("failed to delete menu item") );
 
464
 
 
465
    // don't delete the submenu
 
466
    item2->SetSubMenu(NULL);
 
467
 
 
468
    delete item2;
 
469
 
 
470
    return true;
 
471
}
 
472
 
 
473
bool wxMenuBase::Destroy(wxMenuItem *item)
 
474
{
 
475
    wxCHECK_MSG( item, false, wxT("invalid item in wxMenu::Destroy") );
 
476
 
 
477
    return DoDestroy(item);
 
478
}
 
479
 
 
480
bool wxMenuBase::DoDestroy(wxMenuItem *item)
 
481
{
 
482
    wxMenuItem *item2 = DoRemove(item);
 
483
    wxCHECK_MSG( item2, false, wxT("failed to delete menu item") );
 
484
 
 
485
    delete item2;
 
486
 
 
487
    return true;
 
488
}
 
489
 
 
490
// ----------------------------------------------------------------------------
 
491
// wxMenu searching for items
 
492
// ----------------------------------------------------------------------------
 
493
 
 
494
// Finds the item id matching the given string, wxNOT_FOUND if not found.
 
495
int wxMenuBase::FindItem(const wxString& text) const
 
496
{
 
497
    wxString label = wxMenuItem::GetLabelText(text);
 
498
    for ( wxMenuItemList::compatibility_iterator node = m_items.GetFirst();
 
499
          node;
 
500
          node = node->GetNext() )
 
501
    {
 
502
        wxMenuItem *item = node->GetData();
 
503
        if ( item->IsSubMenu() )
 
504
        {
 
505
            int rc = item->GetSubMenu()->FindItem(label);
 
506
            if ( rc != wxNOT_FOUND )
 
507
                return rc;
 
508
        }
 
509
 
 
510
        // we execute this code for submenus as well to alllow finding them by
 
511
        // name just like the ordinary items
 
512
        if ( !item->IsSeparator() )
 
513
        {
 
514
            if ( item->GetItemLabelText() == label )
 
515
                return item->GetId();
 
516
        }
 
517
    }
 
518
 
 
519
    return wxNOT_FOUND;
 
520
}
 
521
 
 
522
// recursive search for item by id
 
523
wxMenuItem *wxMenuBase::FindItem(int itemId, wxMenu **itemMenu) const
 
524
{
 
525
    if ( itemMenu )
 
526
        *itemMenu = NULL;
 
527
 
 
528
    wxMenuItem *item = NULL;
 
529
    for ( wxMenuItemList::compatibility_iterator node = m_items.GetFirst();
 
530
          node && !item;
 
531
          node = node->GetNext() )
 
532
    {
 
533
        item = node->GetData();
 
534
 
 
535
        if ( item->GetId() == itemId )
 
536
        {
 
537
            if ( itemMenu )
 
538
                *itemMenu = (wxMenu *)this;
 
539
        }
 
540
        else if ( item->IsSubMenu() )
 
541
        {
 
542
            item = item->GetSubMenu()->FindItem(itemId, itemMenu);
 
543
        }
 
544
        else
 
545
        {
 
546
            // don't exit the loop
 
547
            item = NULL;
 
548
        }
 
549
    }
 
550
 
 
551
    return item;
 
552
}
 
553
 
 
554
// non recursive search
 
555
wxMenuItem *wxMenuBase::FindChildItem(int itemid, size_t *ppos) const
 
556
{
 
557
    wxMenuItem *item = NULL;
 
558
    wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
 
559
 
 
560
    size_t pos;
 
561
    for ( pos = 0; node; pos++ )
 
562
    {
 
563
        if ( node->GetData()->GetId() == itemid )
 
564
        {
 
565
            item = node->GetData();
 
566
 
 
567
            break;
 
568
        }
 
569
 
 
570
        node = node->GetNext();
 
571
    }
 
572
 
 
573
    if ( ppos )
 
574
    {
 
575
        *ppos = item ? pos : (size_t)wxNOT_FOUND;
 
576
    }
 
577
 
 
578
    return item;
 
579
}
 
580
 
 
581
// find by position
 
582
wxMenuItem* wxMenuBase::FindItemByPosition(size_t position) const
 
583
{
 
584
    wxCHECK_MSG( position < m_items.GetCount(), NULL,
 
585
                 wxT("wxMenu::FindItemByPosition(): invalid menu index") );
 
586
 
 
587
    return m_items.Item( position )->GetData();
 
588
}
 
589
 
 
590
// ----------------------------------------------------------------------------
 
591
// wxMenu helpers used by derived classes
 
592
// ----------------------------------------------------------------------------
 
593
 
 
594
// Update a menu and all submenus recursively. source is the object that has
 
595
// the update event handlers defined for it. If NULL, the menu or associated
 
596
// window will be used.
 
597
void wxMenuBase::UpdateUI(wxEvtHandler* source)
 
598
{
 
599
    wxWindow * const win = GetWindow();
 
600
 
 
601
    if ( !source && win )
 
602
        source = win->GetEventHandler();
 
603
    if ( !source )
 
604
        source = GetEventHandler();
 
605
    if ( !source )
 
606
        source = this;
 
607
 
 
608
    wxMenuItemList::compatibility_iterator  node = GetMenuItems().GetFirst();
 
609
    while ( node )
 
610
    {
 
611
        wxMenuItem* item = node->GetData();
 
612
        if ( !item->IsSeparator() )
 
613
        {
 
614
            wxWindowID itemid = item->GetId();
 
615
            wxUpdateUIEvent event(itemid);
 
616
            event.SetEventObject( this );
 
617
 
 
618
            if ( source->ProcessEvent(event) )
 
619
            {
 
620
                // if anything changed, update the changed attribute
 
621
                if (event.GetSetText())
 
622
                    SetLabel(itemid, event.GetText());
 
623
                if (event.GetSetChecked())
 
624
                    Check(itemid, event.GetChecked());
 
625
                if (event.GetSetEnabled())
 
626
                    Enable(itemid, event.GetEnabled());
 
627
            }
 
628
 
 
629
            // recurse to the submenus
 
630
            if ( item->GetSubMenu() )
 
631
                item->GetSubMenu()->UpdateUI(source);
 
632
        }
 
633
        //else: item is a separator (which doesn't process update UI events)
 
634
 
 
635
        node = node->GetNext();
 
636
    }
 
637
}
 
638
 
 
639
bool wxMenuBase::SendEvent(int itemid, int checked)
 
640
{
 
641
    wxCommandEvent event(wxEVT_MENU, itemid);
 
642
    event.SetEventObject(this);
 
643
    event.SetInt(checked);
 
644
 
 
645
    wxWindow* const win = GetWindow();
 
646
    wxMenuBar* const mb = GetMenuBar();
 
647
 
 
648
    // Try the menu's event handler first
 
649
    wxEvtHandler *handler = GetEventHandler();
 
650
    if ( handler )
 
651
    {
 
652
        // Indicate to the event processing code that we're going to pass this
 
653
        // event to another handler if it's not processed here to prevent it
 
654
        // from passing the event to wxTheApp: this will be done below if we do
 
655
        // have the associated window.
 
656
        if ( win || mb )
 
657
            event.SetWillBeProcessedAgain();
 
658
 
 
659
        if ( handler->SafelyProcessEvent(event) )
 
660
            return true;
 
661
    }
 
662
 
 
663
    // If this menu is part of the menu bar, process the event there: this will
 
664
    // also propagate it upwards to the window containing the menu bar.
 
665
    if ( mb )
 
666
        return mb->HandleWindowEvent(event);
 
667
 
 
668
    // Try the window the menu was popped up from.
 
669
    if ( win )
 
670
        return win->HandleWindowEvent(event);
 
671
 
 
672
    // Not processed.
 
673
    return false;
 
674
}
 
675
 
 
676
// ----------------------------------------------------------------------------
 
677
// wxMenu attaching/detaching to/from menu bar
 
678
// ----------------------------------------------------------------------------
 
679
 
 
680
wxMenuBar* wxMenuBase::GetMenuBar() const
 
681
{
 
682
    if(GetParent())
 
683
        return GetParent()->GetMenuBar();
 
684
    return m_menuBar;
 
685
}
 
686
 
 
687
void wxMenuBase::Attach(wxMenuBarBase *menubar)
 
688
{
 
689
    // use Detach() instead!
 
690
    wxASSERT_MSG( menubar, wxT("menu can't be attached to NULL menubar") );
 
691
 
 
692
    // use IsAttached() to prevent this from happening
 
693
    wxASSERT_MSG( !m_menuBar, wxT("attaching menu twice?") );
 
694
 
 
695
    m_menuBar = (wxMenuBar *)menubar;
 
696
}
 
697
 
 
698
void wxMenuBase::Detach()
 
699
{
 
700
    // use IsAttached() to prevent this from happening
 
701
    wxASSERT_MSG( m_menuBar, wxT("detaching unattached menu?") );
 
702
 
 
703
    m_menuBar = NULL;
 
704
}
 
705
 
 
706
// ----------------------------------------------------------------------------
 
707
// wxMenu invoking window handling
 
708
// ----------------------------------------------------------------------------
 
709
 
 
710
void wxMenuBase::SetInvokingWindow(wxWindow *win)
 
711
{
 
712
    wxASSERT_MSG( !GetParent(),
 
713
                    "should only be called for top level popup menus" );
 
714
    wxASSERT_MSG( !IsAttached(),
 
715
                    "menus attached to menu bar can't have invoking window" );
 
716
 
 
717
    m_invokingWindow = win;
 
718
}
 
719
 
 
720
wxWindow *wxMenuBase::GetWindow() const
 
721
{
 
722
    // only the top level menus have non-NULL invoking window or a pointer to
 
723
    // the menu bar so recurse upwards until we find it
 
724
    const wxMenuBase *menu = this;
 
725
    while ( menu->GetParent() )
 
726
    {
 
727
        menu = menu->GetParent();
 
728
    }
 
729
 
 
730
    return menu->GetMenuBar() ? menu->GetMenuBar()->GetFrame()
 
731
                              : menu->GetInvokingWindow();
 
732
}
 
733
 
 
734
// ----------------------------------------------------------------------------
 
735
// wxMenu functions forwarded to wxMenuItem
 
736
// ----------------------------------------------------------------------------
 
737
 
 
738
void wxMenuBase::Enable( int itemid, bool enable )
 
739
{
 
740
    wxMenuItem *item = FindItem(itemid);
 
741
 
 
742
    wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
 
743
 
 
744
    item->Enable(enable);
 
745
}
 
746
 
 
747
bool wxMenuBase::IsEnabled( int itemid ) const
 
748
{
 
749
    wxMenuItem *item = FindItem(itemid);
 
750
 
 
751
    wxCHECK_MSG( item, false, wxT("wxMenu::IsEnabled: no such item") );
 
752
 
 
753
    return item->IsEnabled();
 
754
}
 
755
 
 
756
void wxMenuBase::Check( int itemid, bool enable )
 
757
{
 
758
    wxMenuItem *item = FindItem(itemid);
 
759
 
 
760
    wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
 
761
 
 
762
    item->Check(enable);
 
763
}
 
764
 
 
765
bool wxMenuBase::IsChecked( int itemid ) const
 
766
{
 
767
    wxMenuItem *item = FindItem(itemid);
 
768
 
 
769
    wxCHECK_MSG( item, false, wxT("wxMenu::IsChecked: no such item") );
 
770
 
 
771
    return item->IsChecked();
 
772
}
 
773
 
 
774
void wxMenuBase::SetLabel( int itemid, const wxString &label )
 
775
{
 
776
    wxMenuItem *item = FindItem(itemid);
 
777
 
 
778
    wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
 
779
 
 
780
    item->SetItemLabel(label);
 
781
}
 
782
 
 
783
wxString wxMenuBase::GetLabel( int itemid ) const
 
784
{
 
785
    wxMenuItem *item = FindItem(itemid);
 
786
 
 
787
    wxCHECK_MSG( item, wxEmptyString, wxT("wxMenu::GetLabel: no such item") );
 
788
 
 
789
    return item->GetItemLabel();
 
790
}
 
791
 
 
792
void wxMenuBase::SetHelpString( int itemid, const wxString& helpString )
 
793
{
 
794
    wxMenuItem *item = FindItem(itemid);
 
795
 
 
796
    wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
 
797
 
 
798
    item->SetHelp( helpString );
 
799
}
 
800
 
 
801
wxString wxMenuBase::GetHelpString( int itemid ) const
 
802
{
 
803
    wxMenuItem *item = FindItem(itemid);
 
804
 
 
805
    wxCHECK_MSG( item, wxEmptyString, wxT("wxMenu::GetHelpString: no such item") );
 
806
 
 
807
    return item->GetHelp();
 
808
}
 
809
 
 
810
// ----------------------------------------------------------------------------
 
811
// wxMenuBarBase ctor and dtor
 
812
// ----------------------------------------------------------------------------
 
813
 
 
814
wxMenuBarBase::wxMenuBarBase()
 
815
{
 
816
    // not attached yet
 
817
    m_menuBarFrame = NULL;
 
818
}
 
819
 
 
820
wxMenuBarBase::~wxMenuBarBase()
 
821
{
 
822
    WX_CLEAR_LIST(wxMenuList, m_menus);
 
823
}
 
824
 
 
825
// ----------------------------------------------------------------------------
 
826
// wxMenuBar item access: the base class versions manage m_menus list, the
 
827
// derived class should reflect the changes in the real menubar
 
828
// ----------------------------------------------------------------------------
 
829
 
 
830
wxMenu *wxMenuBarBase::GetMenu(size_t pos) const
 
831
{
 
832
    wxMenuList::compatibility_iterator node = m_menus.Item(pos);
 
833
    wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::GetMenu()") );
 
834
 
 
835
    return node->GetData();
 
836
}
 
837
 
 
838
bool wxMenuBarBase::Append(wxMenu *menu, const wxString& title)
 
839
{
 
840
    wxCHECK_MSG( menu, false, wxT("can't append NULL menu") );
 
841
    wxCHECK_MSG( !title.empty(), false, wxT("can't append menu with empty title") );
 
842
 
 
843
    m_menus.Append(menu);
 
844
    menu->Attach(this);
 
845
 
 
846
    return true;
 
847
}
 
848
 
 
849
bool wxMenuBarBase::Insert(size_t pos, wxMenu *menu,
 
850
                           const wxString& title)
 
851
{
 
852
    if ( pos == m_menus.GetCount() )
 
853
    {
 
854
        return wxMenuBarBase::Append(menu, title);
 
855
    }
 
856
    else // not at the end
 
857
    {
 
858
        wxCHECK_MSG( menu, false, wxT("can't insert NULL menu") );
 
859
 
 
860
        wxMenuList::compatibility_iterator node = m_menus.Item(pos);
 
861
        wxCHECK_MSG( node, false, wxT("bad index in wxMenuBar::Insert()") );
 
862
 
 
863
        m_menus.Insert(node, menu);
 
864
        menu->Attach(this);
 
865
 
 
866
        return true;
 
867
    }
 
868
}
 
869
 
 
870
wxMenu *wxMenuBarBase::Replace(size_t pos, wxMenu *menu,
 
871
                               const wxString& WXUNUSED(title))
 
872
{
 
873
    wxCHECK_MSG( menu, NULL, wxT("can't insert NULL menu") );
 
874
 
 
875
    wxMenuList::compatibility_iterator node = m_menus.Item(pos);
 
876
    wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Replace()") );
 
877
 
 
878
    wxMenu *menuOld = node->GetData();
 
879
    node->SetData(menu);
 
880
 
 
881
    menu->Attach(this);
 
882
    menuOld->Detach();
 
883
 
 
884
    return menuOld;
 
885
}
 
886
 
 
887
wxMenu *wxMenuBarBase::Remove(size_t pos)
 
888
{
 
889
    wxMenuList::compatibility_iterator node = m_menus.Item(pos);
 
890
    wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Remove()") );
 
891
 
 
892
    wxMenu *menu = node->GetData();
 
893
    m_menus.Erase(node);
 
894
    menu->Detach();
 
895
 
 
896
    return menu;
 
897
}
 
898
 
 
899
int wxMenuBarBase::FindMenu(const wxString& title) const
 
900
{
 
901
    wxString label = wxMenuItem::GetLabelText(title);
 
902
 
 
903
    size_t count = GetMenuCount();
 
904
    for ( size_t i = 0; i < count; i++ )
 
905
    {
 
906
        wxString title2 = GetMenuLabel(i);
 
907
        if ( (title2 == title) ||
 
908
             (wxMenuItem::GetLabelText(title2) == label) )
 
909
        {
 
910
            // found
 
911
            return (int)i;
 
912
        }
 
913
    }
 
914
 
 
915
    return wxNOT_FOUND;
 
916
 
 
917
}
 
918
 
 
919
// ----------------------------------------------------------------------------
 
920
// wxMenuBar attaching/detaching to/from the frame
 
921
// ----------------------------------------------------------------------------
 
922
 
 
923
void wxMenuBarBase::Attach(wxFrame *frame)
 
924
{
 
925
    wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
 
926
 
 
927
    SetParent(frame);
 
928
    m_menuBarFrame = frame;
 
929
}
 
930
 
 
931
void wxMenuBarBase::Detach()
 
932
{
 
933
    wxASSERT_MSG( IsAttached(), wxT("detaching unattached menubar") );
 
934
 
 
935
    m_menuBarFrame = NULL;
 
936
    SetParent(NULL);
 
937
}
 
938
 
 
939
// ----------------------------------------------------------------------------
 
940
// wxMenuBar searching for items
 
941
// ----------------------------------------------------------------------------
 
942
 
 
943
wxMenuItem *wxMenuBarBase::FindItem(int itemid, wxMenu **menu) const
 
944
{
 
945
    if ( menu )
 
946
        *menu = NULL;
 
947
 
 
948
    wxMenuItem *item = NULL;
 
949
    size_t count = GetMenuCount(), i;
 
950
    wxMenuList::const_iterator it;
 
951
    for ( i = 0, it = m_menus.begin(); !item && (i < count); i++, it++ )
 
952
    {
 
953
        item = (*it)->FindItem(itemid, menu);
 
954
    }
 
955
 
 
956
    return item;
 
957
}
 
958
 
 
959
int wxMenuBarBase::FindMenuItem(const wxString& menu, const wxString& item) const
 
960
{
 
961
    wxString label = wxMenuItem::GetLabelText(menu);
 
962
 
 
963
    int i = 0;
 
964
    wxMenuList::compatibility_iterator node;
 
965
    for ( node = m_menus.GetFirst(); node; node = node->GetNext(), i++ )
 
966
    {
 
967
        if ( label == wxMenuItem::GetLabelText(GetMenuLabel(i)) )
 
968
            return node->GetData()->FindItem(item);
 
969
    }
 
970
 
 
971
    return wxNOT_FOUND;
 
972
}
 
973
 
 
974
// ---------------------------------------------------------------------------
 
975
// wxMenuBar functions forwarded to wxMenuItem
 
976
// ---------------------------------------------------------------------------
 
977
 
 
978
void wxMenuBarBase::Enable(int itemid, bool enable)
 
979
{
 
980
    wxMenuItem *item = FindItem(itemid);
 
981
 
 
982
    wxCHECK_RET( item, wxT("attempt to enable an item which doesn't exist") );
 
983
 
 
984
    item->Enable(enable);
 
985
}
 
986
 
 
987
void wxMenuBarBase::Check(int itemid, bool check)
 
988
{
 
989
    wxMenuItem *item = FindItem(itemid);
 
990
 
 
991
    wxCHECK_RET( item, wxT("attempt to check an item which doesn't exist") );
 
992
    wxCHECK_RET( item->IsCheckable(), wxT("attempt to check an uncheckable item") );
 
993
 
 
994
    item->Check(check);
 
995
}
 
996
 
 
997
bool wxMenuBarBase::IsChecked(int itemid) const
 
998
{
 
999
    wxMenuItem *item = FindItem(itemid);
 
1000
 
 
1001
    wxCHECK_MSG( item, false, wxT("wxMenuBar::IsChecked(): no such item") );
 
1002
 
 
1003
    return item->IsChecked();
 
1004
}
 
1005
 
 
1006
bool wxMenuBarBase::IsEnabled(int itemid) const
 
1007
{
 
1008
    wxMenuItem *item = FindItem(itemid);
 
1009
 
 
1010
    wxCHECK_MSG( item, false, wxT("wxMenuBar::IsEnabled(): no such item") );
 
1011
 
 
1012
    return item->IsEnabled();
 
1013
}
 
1014
 
 
1015
void wxMenuBarBase::SetLabel(int itemid, const wxString& label)
 
1016
{
 
1017
    wxMenuItem *item = FindItem(itemid);
 
1018
 
 
1019
    wxCHECK_RET( item, wxT("wxMenuBar::SetLabel(): no such item") );
 
1020
 
 
1021
    item->SetItemLabel(label);
 
1022
}
 
1023
 
 
1024
wxString wxMenuBarBase::GetLabel(int itemid) const
 
1025
{
 
1026
    wxMenuItem *item = FindItem(itemid);
 
1027
 
 
1028
    wxCHECK_MSG( item, wxEmptyString,
 
1029
                 wxT("wxMenuBar::GetLabel(): no such item") );
 
1030
 
 
1031
    return item->GetItemLabel();
 
1032
}
 
1033
 
 
1034
void wxMenuBarBase::SetHelpString(int itemid, const wxString& helpString)
 
1035
{
 
1036
    wxMenuItem *item = FindItem(itemid);
 
1037
 
 
1038
    wxCHECK_RET( item, wxT("wxMenuBar::SetHelpString(): no such item") );
 
1039
 
 
1040
    item->SetHelp(helpString);
 
1041
}
 
1042
 
 
1043
wxString wxMenuBarBase::GetHelpString(int itemid) const
 
1044
{
 
1045
    wxMenuItem *item = FindItem(itemid);
 
1046
 
 
1047
    wxCHECK_MSG( item, wxEmptyString,
 
1048
                 wxT("wxMenuBar::GetHelpString(): no such item") );
 
1049
 
 
1050
    return item->GetHelp();
 
1051
}
 
1052
 
 
1053
void wxMenuBarBase::UpdateMenus()
 
1054
{
 
1055
    wxMenu* menu;
 
1056
    int nCount = GetMenuCount();
 
1057
    for (int n = 0; n < nCount; n++)
 
1058
    {
 
1059
        menu = GetMenu( n );
 
1060
        if (menu != NULL)
 
1061
            menu->UpdateUI( NULL );
 
1062
    }
 
1063
}
 
1064
 
 
1065
#if WXWIN_COMPATIBILITY_2_8
 
1066
// get or change the label of the menu at given position
 
1067
void wxMenuBarBase::SetLabelTop(size_t pos, const wxString& label)
 
1068
{
 
1069
    SetMenuLabel(pos, label);
 
1070
}
 
1071
 
 
1072
wxString wxMenuBarBase::GetLabelTop(size_t pos) const
 
1073
{
 
1074
    return GetMenuLabelText(pos);
 
1075
}
 
1076
#endif
 
1077
 
 
1078
#endif // wxUSE_MENUS