OSDN Git Service

Avoid opening files during execution of other Ruby script
[molby/Molby.git] / wxSources / menu.mm
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
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
20 #ifndef WX_PRECOMP
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"
26 #endif
27
28 #include "wx/menu.h"
29
30 #include "wx/osx/private.h"
31
32 // other standard headers
33 // ----------------------
34 #include <string.h>
35
36 @implementation wxNSMenu
37
38 - (id) initWithTitle:(NSString*) title
39 {
40     self = [super initWithTitle:title];
41     impl = NULL;
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
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
61 @interface wxNSMenuController : NSObject wxOSX_10_6_AND_LATER(<NSMenuDelegate>)
62 {
63 }
64
65 #if wxOSX_USE_NEEDSUPDATE_HOOK
66 - (void)menuNeedsUpdate:(NSMenu*)smenu;
67 #else
68 - (void)menuWillOpen:(NSMenu *)menu;
69 #endif
70 - (void)menuDidClose:(NSMenu *)menu;
71 - (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item;
72
73 @end
74
75 @implementation wxNSMenuController
76
77 - (id) init
78 {
79     self = [super init];
80     return self;
81 }
82
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
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();
103         if ( wxpeer )
104             wxpeer->HandleMenuOpened();
105     }
106 }
107 #endif
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();
116         if ( wxpeer )
117             wxpeer->HandleMenuClosed();
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
141 @interface NSApplication(MissingAppleMenuCall)
142 - (void)setAppleMenu:(NSMenu *)menu;
143 @end
144
145 class wxMenuCocoaImpl : public wxMenuImpl
146 {
147 public :
148     wxMenuCocoaImpl( wxMenu* peer , wxNSMenu* menu) : wxMenuImpl(peer), m_osxMenu(menu)
149     {
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];
157         // gc aware
158         if ( m_osxMenu )
159             CFRetain(m_osxMenu);
160         [m_osxMenu release];
161     }
162
163     virtual ~wxMenuCocoaImpl();
164
165     virtual void InsertOrAppend(wxMenuItem *pItem, size_t pos)
166     {
167         NSMenuItem* nsmenuitem = (NSMenuItem*) pItem->GetPeer()->GetHMenuItem();
168         // make sure a call of SetSubMenu is also reflected (occurring after Create)
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         
182         if ( pos == (size_t) -1 )
183             [m_osxMenu addItem:nsmenuitem ];
184         else
185             [m_osxMenu insertItem:nsmenuitem atIndex:pos];
186     }
187
188     virtual void Remove( wxMenuItem *pItem )
189     {
190         [m_osxMenu removeItem:(NSMenuItem*) pItem->GetPeer()->GetHMenuItem()];
191     }
192
193     virtual void MakeRoot()
194     {
195         [NSApp setMainMenu:m_osxMenu];
196         [NSApp setAppleMenu:[[m_osxMenu itemAtIndex:0] submenu]];
197                 {
198                         //  2014.4.26. Toshi Nagata
199                         //  Enable "Window" menu
200                         static NSMutableArray *sWindowsMenus = nil;
201                         if (sWindowsMenus == nil) {
202                                 sWindowsMenus = [[NSMutableArray array] retain];
203                         }
204                         id windowsMenu = [m_osxMenu itemWithTitle:@"Window"];
205                         if (windowsMenu && ![sWindowsMenus containsObject:windowsMenu]) {
206                                 [NSApp setWindowsMenu:[windowsMenu submenu]];
207                                 [sWindowsMenus addObject:windowsMenu];
208                         }
209                         //  End Toshi Nagata
210                 }
211     }
212
213     virtual void Enable( bool WXUNUSED(enable) )
214     {
215     }
216
217     virtual void SetTitle( const wxString& text )
218     {
219         wxCFStringRef cfText(text);
220         [m_osxMenu setTitle:cfText.AsNSString()];
221     }
222
223     virtual void PopUp( wxWindow *win, int x, int y )
224     {
225         win->ScreenToClient( &x , &y ) ;
226         NSView *view = win->GetPeer()->GetWXWidget();
227         NSRect frame = [view frame];
228         frame.origin.x = x;
229         frame.origin.y = y;
230         frame.size.width = 1;
231         frame.size.height = 1;
232         NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO];
233         [popUpButtonCell setAutoenablesItems:NO];
234         [popUpButtonCell setAltersStateOfSelectedItem:NO];
235         [popUpButtonCell setMenu:m_osxMenu];
236         [popUpButtonCell selectItem:nil];
237         [popUpButtonCell performClickWithFrame:frame inView:view];
238         [popUpButtonCell release];
239     }
240
241     WXHMENU GetHMenu() { return m_osxMenu; }
242
243     static wxMenuImpl* Create( wxMenu* peer, const wxString& title );
244     static wxMenuImpl* CreateRootMenu( wxMenu* peer );
245 protected :
246     wxNSMenu* m_osxMenu;
247 } ;
248
249 wxMenuCocoaImpl::~wxMenuCocoaImpl()
250 {
251     [m_osxMenu setDelegate:nil];
252     [m_osxMenu setImplementation:nil];
253     // gc aware
254     if ( m_osxMenu )
255         CFRelease(m_osxMenu);
256 }
257
258 wxMenuImpl* wxMenuImpl::Create( wxMenu* peer, const wxString& title )
259 {
260     wxCFStringRef cfText( title );
261     wxNSMenu* menu = [[wxNSMenu alloc] initWithTitle:cfText.AsNSString()];
262     wxMenuImpl* c = new wxMenuCocoaImpl( peer, menu );
263     return c;
264 }
265
266 /*  20140614 Toshi Nagata  */
267 /*  Add the frontmost window to the window menu with the given title  */
268 /*  (for RubyDialog)  */
269 void
270 AddWindowsItemWithTitle(const char *title)
271 {
272         id win = [NSApp keyWindow];
273         if (win != nil) {
274                 [NSApp addWindowsItem:win title:[NSString stringWithUTF8String:title] filename:NO];
275         }
276 }
277 /*  End Toshi Nagata   */