]>
Commit | Line | Data |
---|---|---|
dbeddfb9 SC |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/osx/cocoa/menu.mm | |
3 | // Purpose: wxMenu, wxMenuBar, wxMenuItem | |
4 | // Author: Stefan Csomor | |
5 | // Modified by: | |
6 | // Created: 1998-01-01 | |
dbeddfb9 SC |
7 | // Copyright: (c) Stefan Csomor |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | // ============================================================================ | |
12 | // headers & declarations | |
13 | // ============================================================================ | |
14 | ||
15 | // wxWidgets headers | |
16 | // ----------------- | |
17 | ||
18 | #include "wx/wxprec.h" | |
19 | ||
dbeddfb9 | 20 | #ifndef WX_PRECOMP |
5f4bed8a SC |
21 | #include "wx/log.h" |
22 | #include "wx/app.h" | |
23 | #include "wx/utils.h" | |
24 | #include "wx/frame.h" | |
25 | #include "wx/menuitem.h" | |
dbeddfb9 SC |
26 | #endif |
27 | ||
5f4bed8a SC |
28 | #include "wx/menu.h" |
29 | ||
dbeddfb9 SC |
30 | #include "wx/osx/private.h" |
31 | ||
32 | // other standard headers | |
33 | // ---------------------- | |
34 | #include <string.h> | |
35 | ||
dbeddfb9 SC |
36 | @implementation wxNSMenu |
37 | ||
fbbe829a | 38 | - (id) initWithTitle:(NSString*) title |
dbeddfb9 | 39 | { |
a985b2c8 | 40 | self = [super initWithTitle:title]; |
be136f07 | 41 | impl = NULL; |
dbeddfb9 SC |
42 | return self; |
43 | } | |
44 | ||
45 | - (void)setImplementation: (wxMenuImpl *) theImplementation | |
46 | { | |
47 | impl = theImplementation; | |
48 | } | |
49 | ||
50 | - (wxMenuImpl*) implementation | |
51 | { | |
52 | return impl; | |
53 | } | |
54 | ||
55 | @end | |
56 | ||
5f4bed8a SC |
57 | // this is more compatible, as it is also called for command-key shortcuts |
58 | // and under 10.4, we are not getting a 'close' event however... | |
59 | #define wxOSX_USE_NEEDSUPDATE_HOOK 1 | |
60 | ||
030495ec | 61 | @interface wxNSMenuController : NSObject wxOSX_10_6_AND_LATER(<NSMenuDelegate>) |
dbeddfb9 SC |
62 | { |
63 | } | |
64 | ||
5f4bed8a SC |
65 | #if wxOSX_USE_NEEDSUPDATE_HOOK |
66 | - (void)menuNeedsUpdate:(NSMenu*)smenu; | |
67 | #else | |
dbeddfb9 | 68 | - (void)menuWillOpen:(NSMenu *)menu; |
5f4bed8a | 69 | #endif |
a990673b | 70 | - (void)menuDidClose:(NSMenu *)menu; |
dbeddfb9 SC |
71 | - (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item; |
72 | ||
73 | @end | |
74 | ||
75 | @implementation wxNSMenuController | |
76 | ||
77 | - (id) init | |
78 | { | |
a985b2c8 | 79 | self = [super init]; |
dbeddfb9 SC |
80 | return self; |
81 | } | |
82 | ||
5f4bed8a SC |
83 | #if wxOSX_USE_NEEDSUPDATE_HOOK |
84 | - (void)menuNeedsUpdate:(NSMenu*)smenu | |
85 | { | |
86 | wxNSMenu* menu = (wxNSMenu*) smenu; | |
87 | wxMenuImpl* menuimpl = [menu implementation]; | |
88 | if ( menuimpl ) | |
89 | { | |
90 | wxMenu* wxpeer = (wxMenu*) menuimpl->GetWXPeer(); | |
91 | if ( wxpeer ) | |
92 | wxpeer->HandleMenuOpened(); | |
93 | } | |
94 | } | |
95 | #else | |
dbeddfb9 SC |
96 | - (void)menuWillOpen:(NSMenu *)smenu |
97 | { | |
98 | wxNSMenu* menu = (wxNSMenu*) smenu; | |
99 | wxMenuImpl* menuimpl = [menu implementation]; | |
100 | if ( menuimpl ) | |
101 | { | |
102 | wxMenu* wxpeer = (wxMenu*) menuimpl->GetWXPeer(); | |
3fe48198 SC |
103 | if ( wxpeer ) |
104 | wxpeer->HandleMenuOpened(); | |
dbeddfb9 SC |
105 | } |
106 | } | |
a990673b | 107 | #endif |
dbeddfb9 SC |
108 | |
109 | - (void)menuDidClose:(NSMenu *)smenu | |
110 | { | |
111 | wxNSMenu* menu = (wxNSMenu*) smenu; | |
112 | wxMenuImpl* menuimpl = [menu implementation]; | |
113 | if ( menuimpl ) | |
114 | { | |
115 | wxMenu* wxpeer = (wxMenu*) menuimpl->GetWXPeer(); | |
3fe48198 SC |
116 | if ( wxpeer ) |
117 | wxpeer->HandleMenuClosed(); | |
dbeddfb9 SC |
118 | } |
119 | } | |
120 | ||
121 | - (void)menu:(NSMenu *)smenu willHighlightItem:(NSMenuItem *)item | |
122 | { | |
123 | wxNSMenu* menu = (wxNSMenu*) smenu; | |
124 | wxMenuImpl* menuimpl = [menu implementation]; | |
125 | if ( menuimpl ) | |
126 | { | |
127 | wxMenu* wxpeer = (wxMenu*) menuimpl->GetWXPeer(); | |
128 | if ( [ item isKindOfClass:[wxNSMenuItem class] ] ) | |
129 | { | |
130 | wxMenuItemImpl* menuitemimpl = (wxMenuItemImpl*) [ (wxNSMenuItem*) item implementation ]; | |
131 | if ( wxpeer && menuitemimpl ) | |
132 | { | |
133 | wxpeer->HandleMenuItemHighlighted( menuitemimpl->GetWXPeer() ); | |
134 | } | |
135 | } | |
136 | } | |
137 | } | |
138 | ||
139 | @end | |
140 | ||
03647350 VZ |
141 | @interface NSApplication(MissingAppleMenuCall) |
142 | - (void)setAppleMenu:(NSMenu *)menu; | |
143 | @end | |
ffad7b0d | 144 | |
03647350 | 145 | class wxMenuCocoaImpl : public wxMenuImpl |
dbeddfb9 SC |
146 | { |
147 | public : | |
be136f07 | 148 | wxMenuCocoaImpl( wxMenu* peer , wxNSMenu* menu) : wxMenuImpl(peer), m_osxMenu(menu) |
dbeddfb9 | 149 | { |
be136f07 SC |
150 | static wxNSMenuController* controller = NULL; |
151 | if ( controller == NULL ) | |
152 | { | |
153 | controller = [[wxNSMenuController alloc] init]; | |
154 | } | |
155 | [menu setDelegate:controller]; | |
156 | [m_osxMenu setImplementation:this]; | |
9a038ddc SC |
157 | // gc aware |
158 | if ( m_osxMenu ) | |
159 | CFRetain(m_osxMenu); | |
160 | [m_osxMenu release]; | |
dbeddfb9 | 161 | } |
03647350 | 162 | |
dbeddfb9 | 163 | virtual ~wxMenuCocoaImpl(); |
03647350 VZ |
164 | |
165 | virtual void InsertOrAppend(wxMenuItem *pItem, size_t pos) | |
dbeddfb9 | 166 | { |
b7a015cb | 167 | NSMenuItem* nsmenuitem = (NSMenuItem*) pItem->GetPeer()->GetHMenuItem(); |
58b1ae5e | 168 | // make sure a call of SetSubMenu is also reflected (occurring after Create) |
b7a015cb SC |
169 | // update the native menu item accordingly |
170 | ||
171 | if ( pItem->IsSubMenu() ) | |
172 | { | |
173 | wxMenu* wxsubmenu = pItem->GetSubMenu(); | |
174 | WXHMENU nssubmenu = wxsubmenu->GetHMenu(); | |
175 | if ( [nsmenuitem submenu] != nssubmenu ) | |
176 | { | |
177 | wxsubmenu->GetPeer()->SetTitle( pItem->GetItemLabelText() ); | |
178 | [nsmenuitem setSubmenu:nssubmenu]; | |
179 | } | |
180 | } | |
181 | ||
dbeddfb9 | 182 | if ( pos == (size_t) -1 ) |
b7a015cb | 183 | [m_osxMenu addItem:nsmenuitem ]; |
dbeddfb9 | 184 | else |
b7a015cb | 185 | [m_osxMenu insertItem:nsmenuitem atIndex:pos]; |
dbeddfb9 | 186 | } |
03647350 VZ |
187 | |
188 | virtual void Remove( wxMenuItem *pItem ) | |
dbeddfb9 SC |
189 | { |
190 | [m_osxMenu removeItem:(NSMenuItem*) pItem->GetPeer()->GetHMenuItem()]; | |
191 | } | |
03647350 | 192 | |
dbeddfb9 SC |
193 | virtual void MakeRoot() |
194 | { | |
195 | [NSApp setMainMenu:m_osxMenu]; | |
196 | [NSApp setAppleMenu:[[m_osxMenu itemAtIndex:0] submenu]]; | |
197 | } | |
198 | ||
d8207702 | 199 | virtual void Enable( bool WXUNUSED(enable) ) |
dbeddfb9 SC |
200 | { |
201 | } | |
03647350 | 202 | |
dbeddfb9 SC |
203 | virtual void SetTitle( const wxString& text ) |
204 | { | |
205 | wxCFStringRef cfText(text); | |
206 | [m_osxMenu setTitle:cfText.AsNSString()]; | |
207 | } | |
208 | ||
2cb5d2d2 SC |
209 | virtual void PopUp( wxWindow *win, int x, int y ) |
210 | { | |
211 | win->ScreenToClient( &x , &y ) ; | |
212 | NSView *view = win->GetPeer()->GetWXWidget(); | |
213 | NSRect frame = [view frame]; | |
214 | frame.origin.x = x; | |
215 | frame.origin.y = y; | |
216 | frame.size.width = 1; | |
217 | frame.size.height = 1; | |
218 | NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]; | |
219 | [popUpButtonCell setAutoenablesItems:NO]; | |
220 | [popUpButtonCell setAltersStateOfSelectedItem:NO]; | |
221 | [popUpButtonCell setMenu:m_osxMenu]; | |
222 | [popUpButtonCell selectItem:nil]; | |
223 | [popUpButtonCell performClickWithFrame:frame inView:view]; | |
224 | [popUpButtonCell release]; | |
225 | } | |
226 | ||
dbeddfb9 SC |
227 | WXHMENU GetHMenu() { return m_osxMenu; } |
228 | ||
229 | static wxMenuImpl* Create( wxMenu* peer, const wxString& title ); | |
230 | static wxMenuImpl* CreateRootMenu( wxMenu* peer ); | |
231 | protected : | |
be136f07 | 232 | wxNSMenu* m_osxMenu; |
dbeddfb9 SC |
233 | } ; |
234 | ||
235 | wxMenuCocoaImpl::~wxMenuCocoaImpl() | |
236 | { | |
42c2b729 | 237 | [m_osxMenu setDelegate:nil]; |
be136f07 | 238 | [m_osxMenu setImplementation:nil]; |
9a038ddc SC |
239 | // gc aware |
240 | if ( m_osxMenu ) | |
241 | CFRelease(m_osxMenu); | |
dbeddfb9 SC |
242 | } |
243 | ||
244 | wxMenuImpl* wxMenuImpl::Create( wxMenu* peer, const wxString& title ) | |
245 | { | |
dbeddfb9 SC |
246 | wxCFStringRef cfText( title ); |
247 | wxNSMenu* menu = [[wxNSMenu alloc] initWithTitle:cfText.AsNSString()]; | |
248 | wxMenuImpl* c = new wxMenuCocoaImpl( peer, menu ); | |
dbeddfb9 SC |
249 | return c; |
250 | } |