Send all menu item actions to a dedicated target. This is to ensure
[wxWidgets.git] / src / cocoa / menuitem.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        menuitem.cpp
3 // Purpose:     wxMenuItem implementation
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2002/12/15
7 // RCS-ID:      $Id: 
8 // Copyright:   2002 David Elliott
9 // Licence:     wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21 #ifndef WX_PRECOMP
22     #include "wx/menu.h"
23     #include "wx/menuitem.h"
24     #include "wx/utils.h"
25     #include "wx/frame.h"
26     #include "wx/log.h"
27 #endif
28
29 #include "wx/cocoa/ObjcPose.h"
30 #include "wx/cocoa/autorelease.h"
31
32 #import <AppKit/NSMenuItem.h>
33 #import <AppKit/NSMenu.h>
34 #import <Foundation/NSString.h>
35
36 #if wxUSE_MENUS
37
38 // ----------------------------------------------------------------------------
39 // functions prototypes
40 // ----------------------------------------------------------------------------
41
42 // ============================================================================
43 // @class wxNSMenuItemTarget
44 // ============================================================================
45 @interface wxNSMenuItemTarget : NSObject
46 {
47 }
48
49 - (void)wxMenuItemAction: (id)sender;
50 @end //interface wxNSMenuItemTarget
51
52 @implementation wxNSMenuItemTarget : NSObject
53
54 - (void)wxMenuItemAction: (id)sender
55 {
56     wxLogDebug("wxMenuItemAction");
57     wxMenuItem *item = wxMenuItem::GetFromCocoa(sender);
58     wxCHECK_RET(item,"wxMenuItemAction received but no wxMenuItem exists!");
59
60     wxMenu *menu = item->GetMenu();
61     wxCHECK_RET(menu,"wxMenuItemAction received but wxMenuItem is not in a wxMenu");
62     wxMenuBar *menubar = menu->GetMenuBar();
63     if(menubar)
64     {
65         wxFrame *frame = menubar->GetFrame();
66         wxCHECK_RET(frame, "wxMenuBar MUST be attached to a wxFrame!");
67         frame->Command(item->GetId());
68     }
69 }
70
71 @end //implementation wxNSMenuItemTarget
72
73 // ============================================================================
74 // @class wxPoserNSMenuItem
75 // ============================================================================
76 @interface wxPoserNSMenuItem : NSMenuItem
77 {
78 }
79
80 @end // wxPoserNSMenuItem
81
82 WX_IMPLEMENT_POSER(wxPoserNSMenuItem);
83 @implementation wxPoserNSMenuItem : NSMenuItem
84
85 @end // wxPoseRNSMenuItem
86
87 // ============================================================================
88 // wxMenuItemCocoa implementation
89 // ============================================================================
90 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
91 wxMenuItemCocoaHash wxMenuItemCocoa::sm_cocoaHash;
92
93 struct objc_object *wxMenuItemCocoa::sm_cocoaTarget = [[wxNSMenuItemTarget alloc] init];
94
95 // ----------------------------------------------------------------------------
96 // wxMenuItemBase
97 // ----------------------------------------------------------------------------
98
99 wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
100                                 int itemid,
101                                 const wxString& name,
102                                 const wxString& help,
103                                 wxItemKind kind,
104                                 wxMenu *subMenu)
105 {
106     return new wxMenuItem(parentMenu, itemid, name, help, kind, subMenu);
107 }
108
109 /* static */
110 wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
111 {
112     return wxStripMenuCodes(text);
113 }
114
115 // ----------------------------------------------------------------------------
116 // ctor & dtor
117 // ----------------------------------------------------------------------------
118 wxMenuItemCocoa::wxMenuItemCocoa(wxMenu *pParentMenu,
119                        int itemid,
120                        const wxString& strName,
121                        const wxString& strHelp,
122                        wxItemKind kind,
123                        wxMenu *pSubMenu)
124           : wxMenuItemBase(pParentMenu, itemid, strName, strHelp, kind, pSubMenu)
125 {
126     wxAutoNSAutoreleasePool pool;
127     NSString *menuTitle = [[NSString alloc] initWithCString: wxStripMenuCodes(strName).c_str()];
128     m_cocoaNSMenuItem = [[NSMenuItem alloc] initWithTitle:menuTitle action:@selector(wxMenuItemAction:) keyEquivalent:@""];
129     sm_cocoaHash.insert(wxMenuItemCocoaHash::value_type(m_cocoaNSMenuItem,this));
130     [m_cocoaNSMenuItem setTarget:sm_cocoaTarget];
131     if(pSubMenu)
132     {
133         wxASSERT(pSubMenu->GetNSMenu());
134         [pSubMenu->GetNSMenu() setTitle:menuTitle];
135         [m_cocoaNSMenuItem setSubmenu:pSubMenu->GetNSMenu()];
136     }
137     [menuTitle release];
138 }
139
140 wxMenuItem::~wxMenuItem()
141 {
142     sm_cocoaHash.erase(m_cocoaNSMenuItem);
143     [m_cocoaNSMenuItem release];
144 }
145
146 // ----------------------------------------------------------------------------
147 // misc
148 // ----------------------------------------------------------------------------
149
150 // change item state
151 // -----------------
152
153 void wxMenuItem::Enable(bool bDoEnable)
154 {
155     wxMenuItemBase::Enable(bDoEnable);
156 }
157
158 void wxMenuItem::Check(bool bDoCheck)
159 {
160     wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
161     wxMenuItemBase::Check(bDoCheck);
162 }
163
164 void wxMenuItem::SetText(const wxString& label)
165 {
166     wxMenuItemBase::SetText(label);
167 }
168
169 void wxMenuItem::SetCheckable(bool checkable)
170 {
171     wxMenuItemBase::SetCheckable(checkable);
172 }
173
174 #endif // wxUSE_MENUS