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 43bool 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 51wxMenu::~wxMenu() 52{ 53 DisassociateNSMenu(m_cocoaNSMenu); 54 if(!m_cocoaDeletes) 55 [m_cocoaNSMenu release]; 56} 57 58wxMenuItem* 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 67wxMenuItem* 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 76wxMenuItem* 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. 95void 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 106void wxMenu::Cocoa_dealloc() 107{ 108 if(m_cocoaDeletes) 109 delete this; 110} 111 112// ============================================================================ 113// wxMenuBar implementation 114// ============================================================================ 115 116bool 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 129wxMenuBar::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 140wxMenuBar::~wxMenuBar() 141{ 142 [m_cocoaNSMenu release]; 143} 144 145bool 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 165bool 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 189wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) 190{ 191 return NULL; 192} 193 194wxMenu *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 205void wxMenuBar::EnableTop(size_t pos, bool enable) 206{ 207} 208 209bool wxMenuBar::IsEnabledTop(size_t pos) const 210{ 211 return false; 212} 213 214void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label) 215{ 216} 217 218wxString 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 226void wxMenuBar::Attach(wxFrame *frame) 227{ 228 wxMenuBarBase::Attach(frame); 229} 230 231void wxMenuBar::Detach() 232{ 233 wxMenuBarBase::Detach(); 234} 235 236wxSize wxMenuBar::DoGetBestClientSize() const 237{ 238 return wxDefaultSize; 239} 240 241#endif // wxUSE_MENUS 242