1. implemented radio menu items for wxGTK
[wxWidgets.git] / src / msw / menuitem.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: menuitem.cpp
3 // Purpose: wxMenuItem implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 11.11.97
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "menuitem.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_MENUS
32
33 #ifndef WX_PRECOMP
34 #include "wx/font.h"
35 #include "wx/bitmap.h"
36 #include "wx/settings.h"
37 #include "wx/font.h"
38 #include "wx/window.h"
39 #include "wx/accel.h"
40 #include "wx/menu.h"
41 #include "wx/string.h"
42 #endif
43
44 #include "wx/menuitem.h"
45 #include "wx/log.h"
46
47 #if wxUSE_ACCEL
48 #include "wx/accel.h"
49 #endif // wxUSE_ACCEL
50
51 #include "wx/msw/private.h"
52
53 // ---------------------------------------------------------------------------
54 // macro
55 // ---------------------------------------------------------------------------
56
57 // hide the ugly cast
58 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
59
60 // conditional compilation
61 #if wxUSE_OWNER_DRAWN
62 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
63 #else // !wxUSE_OWNER_DRAWN
64 #define OWNER_DRAWN_ONLY( code )
65 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
66
67 // ============================================================================
68 // implementation
69 // ============================================================================
70
71 // ----------------------------------------------------------------------------
72 // dynamic classes implementation
73 // ----------------------------------------------------------------------------
74
75 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
76
77 // ----------------------------------------------------------------------------
78 // wxMenuItem
79 // ----------------------------------------------------------------------------
80
81 // ctor & dtor
82 // -----------
83
84 wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
85 int id,
86 const wxString& text,
87 const wxString& strHelp,
88 wxItemKind kind,
89 wxMenu *pSubMenu)
90 : wxMenuItemBase(pParentMenu, id, text, strHelp, kind, pSubMenu)
91 #if wxUSE_OWNER_DRAWN
92 , wxOwnerDrawn(GetLabelFromText(text), kind == wxItem_Check)
93 #endif // owner drawn
94 {
95 wxASSERT_MSG( pParentMenu != NULL, wxT("a menu item should have a parent") );
96
97 #if wxUSE_OWNER_DRAWN
98 // set default menu colors
99 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
100
101 SetTextColour(SYS_COLOR(MENUTEXT));
102 SetBackgroundColour(SYS_COLOR(MENU));
103
104 #undef SYS_COLOR
105
106 // we don't want normal items be owner-drawn
107 ResetOwnerDrawn();
108
109 // tell the owner drawing code to to show the accel string as well
110 SetAccelString(text.AfterFirst(_T('\t')));
111 #endif // wxUSE_OWNER_DRAWN
112 }
113
114 wxMenuItem::~wxMenuItem()
115 {
116 }
117
118 // misc
119 // ----
120
121 // return the id for calling Win32 API functions
122 int wxMenuItem::GetRealId() const
123 {
124 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
125 }
126
127 // get item state
128 // --------------
129
130 bool wxMenuItem::IsChecked() const
131 {
132 int flag = ::GetMenuState(GetHMenuOf(m_parentMenu), GetId(), MF_BYCOMMAND);
133
134 return (flag & MF_CHECKED) != 0;
135 }
136
137 /* static */
138 wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
139 {
140 return wxStripMenuCodes(text);
141 }
142
143 // change item state
144 // -----------------
145
146 void wxMenuItem::Enable(bool enable)
147 {
148 if ( m_isEnabled == enable )
149 return;
150
151 long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
152 GetRealId(),
153 MF_BYCOMMAND |
154 (enable ? MF_ENABLED : MF_GRAYED));
155
156 if ( rc == -1 ) {
157 wxLogLastError(wxT("EnableMenuItem"));
158 }
159
160 wxMenuItemBase::Enable(enable);
161 }
162
163 void wxMenuItem::Check(bool check)
164 {
165 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
166
167 if ( m_isChecked == check )
168 return;
169
170 long rc = CheckMenuItem(GetHMenuOf(m_parentMenu),
171 GetRealId(),
172 MF_BYCOMMAND |
173 (check ? MF_CHECKED : MF_UNCHECKED));
174
175 if ( rc == -1 ) {
176 wxLogLastError(wxT("CheckMenuItem"));
177 }
178
179 wxMenuItemBase::Check(check);
180 }
181
182 void wxMenuItem::SetText(const wxString& text)
183 {
184 // don't do anything if label didn't change
185 if ( m_text == text )
186 return;
187
188 wxMenuItemBase::SetText(text);
189 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
190
191 HMENU hMenu = GetHMenuOf(m_parentMenu);
192 wxCHECK_RET( hMenu, wxT("menuitem without menu") );
193
194 #if wxUSE_ACCEL
195 m_parentMenu->UpdateAccel(this);
196 #endif // wxUSE_ACCEL
197
198 UINT id = GetRealId();
199 UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
200 if ( flagsOld == 0xFFFFFFFF )
201 {
202 wxLogLastError(wxT("GetMenuState"));
203 }
204 else
205 {
206 if ( IsSubMenu() )
207 {
208 // high byte contains the number of items in a submenu for submenus
209 flagsOld &= 0xFF;
210 flagsOld |= MF_POPUP;
211 }
212
213 LPCTSTR data;
214
215 #if wxUSE_OWNER_DRAWN
216 if ( IsOwnerDrawn() )
217 {
218 flagsOld |= MF_OWNERDRAW;
219 data = (LPCTSTR)this;
220 }
221 else
222 #endif //owner drawn
223 {
224 flagsOld |= MF_STRING;
225 data = (wxChar*) text.c_str();
226 }
227
228 if ( ::ModifyMenu(hMenu, id,
229 MF_BYCOMMAND | flagsOld,
230 id, data) == (int)0xFFFFFFFF )
231 {
232 wxLogLastError(wxT("ModifyMenu"));
233 }
234 }
235 }
236
237 void wxMenuItem::SetCheckable(bool checkable)
238 {
239 wxMenuItemBase::SetCheckable(checkable);
240 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetCheckable(checkable) );
241 }
242
243 // ----------------------------------------------------------------------------
244 // wxMenuItemBase
245 // ----------------------------------------------------------------------------
246
247 wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
248 int id,
249 const wxString& name,
250 const wxString& help,
251 wxItemKind kind,
252 wxMenu *subMenu)
253 {
254 return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
255 }
256
257 #endif // wxUSE_MENUS