]> git.saurik.com Git - wxWidgets.git/blame - src/osx/menuitem_osx.cpp
Applied #10753: WarpPointer() for Mac
[wxWidgets.git] / src / osx / menuitem_osx.cpp
CommitLineData
524c47aa
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/menuitem_osx.cpp
3// Purpose: wxMenuItem implementation
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id: menuitem.cpp 54129 2008-06-11 19:30:52Z SC $
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
11fed901
SC
14#if wxUSE_MENUS
15
524c47aa
SC
16#include "wx/menuitem.h"
17#include "wx/stockitem.h"
18
19#ifndef WX_PRECOMP
20 #include "wx/app.h"
21 #include "wx/menu.h"
22#endif // WX_PRECOMP
23
24#include "wx/osx/private.h"
25
26IMPLEMENT_ABSTRACT_CLASS( wxMenuItemImpl , wxObject )
27
28wxMenuItemImpl::~wxMenuItemImpl()
29{
30}
31
32IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
33
34wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
35 int id,
36 const wxString& t,
37 const wxString& strHelp,
38 wxItemKind kind,
39 wxMenu *pSubMenu)
40 :wxMenuItemBase(pParentMenu, id, t, strHelp, kind, pSubMenu)
41{
42 wxASSERT_MSG( id != 0 || pSubMenu != NULL , wxT("A MenuItem ID of Zero does not work under Mac") ) ;
43
44 // In other languages there is no difference in naming the Exit/Quit menu item between MacOS and Windows guidelines
45 // therefore these item must not be translated
46 if ( wxStripMenuCodes(m_text).Upper() == wxT("EXIT") )
47 m_text = wxT("Quit\tCtrl+Q") ;
48
49 m_radioGroup.start = -1;
50 m_isRadioGroupStart = false;
03647350 51
524c47aa
SC
52 wxString text = wxStripMenuCodes(m_text);
53 if (text.IsEmpty() && !IsSeparator())
54 {
55 wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
56 text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
57 }
03647350 58
524c47aa 59 wxAcceleratorEntry *entry = wxAcceleratorEntry::Create( m_text ) ;
1ea5ef01
SC
60 // use accessors for ID and Kind because they might have been changed in the base constructor
61 m_peer = wxMenuItemImpl::Create( this, pParentMenu, GetId(), text, entry, strHelp, GetKind(), pSubMenu );
524c47aa
SC
62 delete entry;
63}
64
65wxMenuItem::~wxMenuItem()
66{
67 delete m_peer;
68}
69
70// change item state
71// -----------------
72
73void wxMenuItem::SetBitmap(const wxBitmap& bitmap)
74{
75 m_bitmap = bitmap;
76 UpdateItemBitmap();
77}
78
79void wxMenuItem::Enable(bool bDoEnable)
80{
81 if (( m_isEnabled != bDoEnable
82 // avoid changing menuitem state when menu is disabled
83 // eg. BeginAppModalStateForWindow() will disable menus and ignore this change
84 // which in turn causes m_isEnabled to become out of sync with real menuitem state
85#if wxOSX_USE_CARBON
03647350 86 && !(m_parentMenu && !IsMenuItemEnabled(MAC_WXHMENU(m_parentMenu->GetHMenu()), 0))
524c47aa
SC
87#endif
88 )
89 // always update builtin menuitems
90 || ( GetId() == wxApp::s_macPreferencesMenuItemId
91 || GetId() == wxApp::s_macExitMenuItemId
92 || GetId() == wxApp::s_macAboutMenuItemId
93 ))
94 {
95 wxMenuItemBase::Enable( bDoEnable ) ;
96 UpdateItemStatus() ;
97 }
98}
99
100void wxMenuItem::UncheckRadio()
101{
102 if ( m_isChecked )
103 {
104 wxMenuItemBase::Check( false ) ;
105 UpdateItemStatus() ;
106 }
107}
108
109void wxMenuItem::Check(bool bDoCheck)
110{
111 wxCHECK_RET( IsCheckable() && !IsSeparator(), wxT("only checkable items may be checked") );
112
113 if ( m_isChecked != bDoCheck )
114 {
115 if ( GetKind() == wxITEM_RADIO )
116 {
117 if ( bDoCheck )
118 {
119 wxMenuItemBase::Check( bDoCheck ) ;
120 UpdateItemStatus() ;
121
122 // get the index of this item in the menu
123 const wxMenuItemList& items = m_parentMenu->GetMenuItems();
124 int pos = items.IndexOf(this);
125 wxCHECK_RET( pos != wxNOT_FOUND,
9a83f860 126 wxT("menuitem not found in the menu items list?") );
524c47aa
SC
127
128 // get the radio group range
129 int start, end;
130
131 if ( m_isRadioGroupStart )
132 {
133 // we already have all information we need
134 start = pos;
135 end = m_radioGroup.end;
136 }
137 else // next radio group item
138 {
139 // get the radio group end from the start item
140 start = m_radioGroup.start;
141 end = items.Item(start)->GetData()->m_radioGroup.end;
142 }
143
144 // also uncheck all the other items in this radio group
145 wxMenuItemList::compatibility_iterator node = items.Item(start);
146 for ( int n = start; n <= end && node; n++ )
147 {
148 if ( n != pos )
149 ((wxMenuItem*)node->GetData())->UncheckRadio();
150
151 node = node->GetNext();
152 }
153 }
154 }
155 else
156 {
157 wxMenuItemBase::Check( bDoCheck ) ;
158 UpdateItemStatus() ;
159 }
160 }
161}
162
163void wxMenuItem::SetItemLabel(const wxString& text)
164{
165 // don't do anything if label didn't change
166 if ( m_text == text )
167 return;
168
169 wxMenuItemBase::SetItemLabel(text);
170
171 UpdateItemText() ;
172}
173
174
175void wxMenuItem::UpdateItemBitmap()
176{
177 if ( !m_parentMenu )
178 return;
03647350 179
524c47aa
SC
180 if ( m_bitmap.Ok() )
181 {
182 m_peer->SetBitmap( m_bitmap );
183 }
184}
185
186void wxMenuItem::UpdateItemStatus()
187{
188 if ( !m_parentMenu )
189 return ;
190
191 if ( IsSeparator() )
192 return ;
03647350 193
524c47aa
SC
194 if ( IsCheckable() && IsChecked() )
195 m_peer->Check( true );
196 else
197 m_peer->Check( false );
03647350 198
524c47aa
SC
199 m_peer->Enable( IsEnabled() );
200}
201
202void wxMenuItem::UpdateItemText()
203{
204 if ( !m_parentMenu )
205 return ;
206
207 wxString text = wxStripMenuCodes(m_text);
208 if (text.IsEmpty() && !IsSeparator())
209 {
210 wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
211 text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
212 }
03647350 213
524c47aa
SC
214 wxAcceleratorEntry *entry = wxAcceleratorEntry::Create( m_text ) ;
215 m_peer->SetLabel( text, entry );
216 delete entry ;
217}
218
219// radio group stuff
220// -----------------
221
222void wxMenuItem::SetAsRadioGroupStart()
223{
224 m_isRadioGroupStart = true;
225}
226
227void wxMenuItem::SetRadioGroupStart(int start)
228{
229 wxASSERT_MSG( !m_isRadioGroupStart,
230 wxT("should only be called for the next radio items") );
231
232 m_radioGroup.start = start;
233}
234
235void wxMenuItem::SetRadioGroupEnd(int end)
236{
237 wxASSERT_MSG( m_isRadioGroupStart,
238 wxT("should only be called for the first radio item") );
239
240 m_radioGroup.end = end;
241}
242
243// ----------------------------------------------------------------------------
244// wxMenuItemBase
245// ----------------------------------------------------------------------------
246
247wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
248 int id,
249 const wxString& name,
250 const wxString& help,
251 wxItemKind kind,
252 wxMenu *subMenu)
253{
254 return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
255}
11fed901
SC
256
257#endif