Document domain parameter of wxTranslations::GetTranslatedString().
[wxWidgets.git] / src / cocoa / menu.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/menu.mm
3 // Purpose:     wxMenu and wxMenuBar implementation
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2002/12/09
7 // Copyright:   (c) 2002 David Elliott
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/wxprec.h"
20
21 #include "wx/menu.h"
22
23 #ifndef WX_PRECOMP
24     #include "wx/log.h"
25 #endif // WX_PRECOMP
26
27 #include "wx/cocoa/autorelease.h"
28 #include "wx/cocoa/string.h"
29
30 #import <Foundation/NSString.h>
31 #include "wx/cocoa/objc/NSMenu.h"
32
33 #if wxUSE_MENUS
34
35 // ----------------------------------------------------------------------------
36 // globals
37 // ----------------------------------------------------------------------------
38
39 // ============================================================================
40 // wxMenu implementation
41 // ============================================================================
42
43 bool wxMenu::Create(const wxString& title, long style)
44 {
45     wxAutoNSAutoreleasePool pool;
46     m_cocoaNSMenu = [[WX_GET_OBJC_CLASS(WXNSMenu) alloc] initWithTitle: wxNSStringWithWxString(title)];
47     AssociateNSMenu(m_cocoaNSMenu);
48     return true;
49 }
50
51 wxMenu::~wxMenu()
52 {
53     DisassociateNSMenu(m_cocoaNSMenu);
54     if(!m_cocoaDeletes)
55         [m_cocoaNSMenu release];
56 }
57
58 wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
59 {
60     wxAutoNSAutoreleasePool pool;
61     if(!wxMenuBase::DoAppend(item))
62         return NULL;
63     [m_cocoaNSMenu addItem: item->GetNSMenuItem()];
64     return item;
65 }
66
67 wxMenuItem* wxMenu::DoInsert(unsigned long pos, wxMenuItem *item)
68 {
69     wxAutoNSAutoreleasePool pool;
70     if(!wxMenuBase::DoInsert(pos,item))
71         return NULL;
72     [m_cocoaNSMenu insertItem:item->GetNSMenuItem() atIndex:pos];
73     return item;
74 }
75
76 wxMenuItem* wxMenu::DoRemove(wxMenuItem *item)
77 {
78     wxAutoNSAutoreleasePool pool;
79     wxMenuItem *retitem = wxMenuBase::DoRemove(item);
80     wxASSERT(retitem->GetNSMenuItem());
81     [m_cocoaNSMenu removeItem:retitem->GetNSMenuItem()];
82     return retitem;
83 }
84
85 // This autoreleases the menu on the assumption that something is
86 // going to retain it shortly (for instance, it is going to be returned from
87 // an overloaded [NSStatusItem menu] or from the applicationDockMenu:
88 // NSApplication delegate method.
89 //
90 // It then sets a bool flag m_cocoaDeletes.  When the NSMenu is dealloc'd
91 // (dealloc is the Cocoa destructor) we delete ourselves.  In this manner we
92 // can be available for Cocoa calls until Cocoa is finished with us.
93 //
94 // I can see very few reasons to undo this.  Nevertheless, it is implemented.
95 void wxMenu::SetCocoaDeletes(bool cocoaDeletes)
96 {
97     if(m_cocoaDeletes==cocoaDeletes)
98         return;
99     m_cocoaDeletes = cocoaDeletes;
100     if(m_cocoaDeletes)
101         [m_cocoaNSMenu autorelease];
102     else
103         [m_cocoaNSMenu retain];
104 }
105
106 void wxMenu::Cocoa_dealloc()
107 {
108     if(m_cocoaDeletes)
109         delete this;
110 }
111
112 // ============================================================================
113 // wxMenuBar implementation
114 // ============================================================================
115
116 bool wxMenuBar::Create(long style)
117 {
118     wxAutoNSAutoreleasePool pool;
119     m_cocoaNSMenu = [[NSMenu alloc] initWithTitle: @"wxMenuBar"];
120
121     NSMenuItem *dummyItem = [[NSMenuItem alloc] initWithTitle:@"App menu"
122         /* Note: title gets clobbered by app name anyway */
123         action:nil keyEquivalent:@""];
124     [m_cocoaNSMenu addItem:dummyItem];
125     [dummyItem release];
126     return true;
127 }
128
129 wxMenuBar::wxMenuBar(size_t n,
130                      wxMenu *menus[],
131                      const wxString titles[],
132                      long style)
133 {
134     Create(style);
135
136     for ( size_t i = 0; i < n; ++i )
137         Append(menus[i], titles[i]);
138 }
139
140 wxMenuBar::~wxMenuBar()
141 {
142     [m_cocoaNSMenu release];
143 }
144
145 bool wxMenuBar::Append( wxMenu *menu, const wxString &title )
146 {
147     wxAutoNSAutoreleasePool pool;
148     wxLogTrace(wxTRACE_COCOA,wxT("append menu=%p, title=%s"),menu,title.c_str());
149     if(!wxMenuBarBase::Append(menu,title))
150         return false;
151     wxASSERT(menu);
152     wxASSERT(menu->GetNSMenu());
153     NSString *menuTitle = wxInitNSStringWithWxString([NSString alloc], wxStripMenuCodes(title));
154     NSMenuItem *newItem = [[NSMenuItem alloc] initWithTitle:menuTitle action:NULL keyEquivalent:@""];
155     [menu->GetNSMenu() setTitle:menuTitle];
156     [newItem setSubmenu:menu->GetNSMenu()];
157
158     [m_cocoaNSMenu addItem:newItem];
159
160     [menuTitle release];
161     [newItem release];
162     return true;
163 }
164
165 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
166 {
167     wxAutoNSAutoreleasePool pool;
168     wxLogTrace(wxTRACE_COCOA,wxT("insert pos=%lu, menu=%p, title=%s"),pos,menu,title.c_str());
169     // Get the current menu at this position
170     wxMenu *nextmenu = GetMenu(pos);
171     if(!wxMenuBarBase::Insert(pos,menu,title))
172         return false;
173     wxASSERT(menu);
174     wxASSERT(menu->GetNSMenu());
175     NSString *menuTitle = wxInitNSStringWithWxString([NSString alloc], title);
176     NSMenuItem *newItem = [[NSMenuItem alloc] initWithTitle:menuTitle action:NULL keyEquivalent:@""];
177     [menu->GetNSMenu() setTitle:menuTitle];
178     [newItem setSubmenu:menu->GetNSMenu()];
179
180     int itemindex = [m_cocoaNSMenu indexOfItemWithSubmenu:nextmenu->GetNSMenu()];
181     wxASSERT(itemindex>=0);
182     [m_cocoaNSMenu insertItem:newItem atIndex:itemindex];
183
184     [menuTitle release];
185     [newItem release];
186     return true;
187 }
188
189 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
190 {
191     return NULL;
192 }
193
194 wxMenu *wxMenuBar::Remove(size_t pos)
195 {
196     wxMenu *menu = wxMenuBarBase::Remove(pos);
197     wxASSERT(menu);
198     int itemindex = [GetNSMenu() indexOfItemWithSubmenu:menu->GetNSMenu()];
199     wxASSERT(itemindex>=0);
200     [m_cocoaNSMenu removeItemAtIndex:itemindex];
201     return menu;
202 }
203
204
205 void wxMenuBar::EnableTop(size_t pos, bool enable)
206 {
207 }
208
209 bool wxMenuBar::IsEnabledTop(size_t pos) const
210 {
211     return false;
212 }
213
214 void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
215 {
216 }
217
218 wxString wxMenuBar::GetMenuLabel(size_t pos) const
219 {
220     wxMenu *menu = GetMenu(pos);
221     int itemindex = [m_cocoaNSMenu indexOfItemWithSubmenu:menu->GetNSMenu()];
222     wxASSERT(itemindex>=0);
223     return wxStringWithNSString([[m_cocoaNSMenu itemAtIndex:itemindex] title]);
224 }
225
226 void wxMenuBar::Attach(wxFrame *frame)
227 {
228     wxMenuBarBase::Attach(frame);
229 }
230
231 void wxMenuBar::Detach()
232 {
233     wxMenuBarBase::Detach();
234 }
235
236 wxSize wxMenuBar::DoGetBestClientSize() const
237 {
238     return wxDefaultSize;
239 }
240
241 #endif // wxUSE_MENUS