1. implemented radio menu items for wxGTK
[wxWidgets.git] / src / os2 / menuitem.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: menuitem.cpp
3 // Purpose: wxMenuItem implementation
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/10/98
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
15
16 #ifdef __GNUG__
17 #pragma implementation "menuitem.h"
18 #endif
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/font.h"
25 #include "wx/bitmap.h"
26 #include "wx/settings.h"
27 #include "wx/font.h"
28 #include "wx/window.h"
29 #include "wx/accel.h"
30 #include "wx/menu.h"
31 #include "wx/string.h"
32 #endif
33
34 #include "wx/menuitem.h"
35 #include "wx/log.h"
36
37 #if wxUSE_ACCEL
38 #include "wx/accel.h"
39 #endif // wxUSE_ACCEL
40
41 #include "wx/os2/private.h"
42
43 // ---------------------------------------------------------------------------
44 // macro
45 // ---------------------------------------------------------------------------
46
47 // hide the ugly cast
48 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
49
50 // conditional compilation
51 #if wxUSE_OWNER_DRAWN
52 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
53 #else // !wxUSE_OWNER_DRAWN
54 #define OWNER_DRAWN_ONLY( code )
55 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
56
57 // ----------------------------------------------------------------------------
58 // static function for translating menu labels
59 // ----------------------------------------------------------------------------
60
61 static wxString TextToLabel(const wxString& rTitle)
62 {
63 wxString Title;
64 const wxChar *pc;
65 for (pc = rTitle.c_str(); *pc != wxT('\0'); pc++ )
66 {
67 if (*pc == wxT('&') )
68 {
69 if (*(pc+1) == wxT('&'))
70 {
71 pc++;
72 Title << wxT('&');
73 }
74 else
75 Title << wxT('~');
76 }
77 else
78 {
79 if ( *pc == wxT('~') )
80 {
81 // tildes must be doubled to prevent them from being
82 // interpreted as accelerator character prefix by PM ???
83 Title << *pc;
84 }
85 Title << *pc;
86 }
87 }
88 return Title;
89 }
90
91 // ============================================================================
92 // implementation
93 // ============================================================================
94
95 // ----------------------------------------------------------------------------
96 // dynamic classes implementation
97 // ----------------------------------------------------------------------------
98
99 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
100
101 // ----------------------------------------------------------------------------
102 // wxMenuItem
103 // ----------------------------------------------------------------------------
104
105 // ctor & dtor
106 // -----------
107
108 wxMenuItem::wxMenuItem(
109 wxMenu* pParentMenu
110 , int nId
111 , const wxString& rText
112 , const wxString& rStrHelp
113 , wxItemKind kind
114 , wxMenu* pSubMenu
115 )
116 : wxMenuItemBase(pParentMenu, nId, rText, rStrHelp, kind, pSubMenu)
117 #if wxUSE_OWNER_DRAWN
118 , wxOwnerDrawn( TextToLabel(rText)
119 ,bCheckable
120 )
121 #endif // owner drawn
122 {
123 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
124
125 #if wxUSE_OWNER_DRAWN
126
127 //
128 // Set default menu colors
129 //
130 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
131
132 SetTextColour(SYS_COLOR(MENUTEXT));
133 SetBackgroundColour(SYS_COLOR(MENU));
134
135 //
136 // We don't want normal items be owner-drawn
137 //
138 ResetOwnerDrawn();
139
140 #undef SYS_COLOR
141 #endif // wxUSE_OWNER_DRAWN
142
143 m_text = TextToLabel(rText);
144
145 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
146 m_vMenuData.id= nId;
147 } // end of wxMenuItem::wxMenuItem
148
149 wxMenuItem::~wxMenuItem()
150 {
151 } // end of wxMenuItem::~wxMenuItem
152
153 //
154 // Misc
155 // ----
156
157 //
158 // Return the id for calling Win32 API functions
159 //
160 int wxMenuItem::GetRealId() const
161 {
162 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
163 } // end of wxMenuItem::GetRealId
164
165 //
166 // Get item state
167 // --------------
168 bool wxMenuItem::IsChecked() const
169 {
170 USHORT uFlag = SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu)
171 ,MM_QUERYITEMATTR
172 ,MPFROM2SHORT(GetId(), TRUE)
173 ,MPFROMSHORT(MIA_CHECKED)
174 ));
175
176 return (uFlag & MIA_CHECKED);
177 } // end of wxMenuItem::IsChecked
178
179 wxString wxMenuItemBase::GetLabelFromText(
180 const wxString& rText
181 )
182 {
183 wxString label;
184 for ( const wxChar *pc = rText.c_str(); *pc; pc++ )
185 {
186 if ( *pc == wxT('~') || *pc == wxT('&') )
187 {
188 // '~' is the escape character for GTK+ and '&' is the one for
189 // wxWindows - skip both of them
190 continue;
191 }
192
193 label += *pc;
194 }
195 return label;
196 }
197
198 // change item state
199 // -----------------
200
201 void wxMenuItem::Enable(
202 bool bEnable
203 )
204 {
205 bool bOk;
206
207 if (m_isEnabled == bEnable)
208 return;
209 if (bEnable)
210 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
211 ,MM_SETITEMATTR
212 ,MPFROM2SHORT(GetRealId(), TRUE)
213 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
214 );
215 else
216 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
217 ,MM_SETITEMATTR
218 ,MPFROM2SHORT(GetRealId(), TRUE)
219 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
220 );
221 if (!bOk)
222 {
223 wxLogLastError("EnableMenuItem");
224 }
225 wxMenuItemBase::Enable(bEnable);
226 } // end of wxMenuItem::Enable
227
228 void wxMenuItem::Check(
229 bool bCheck
230 )
231 {
232 bool bOk;
233
234 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
235 if (m_isChecked == bCheck)
236 return;
237 if (bCheck)
238 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
239 ,MM_SETITEMATTR
240 ,MPFROM2SHORT(GetRealId(), TRUE)
241 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
242 );
243 else
244 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
245 ,MM_SETITEMATTR
246 ,MPFROM2SHORT(GetRealId(), TRUE)
247 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
248 );
249 if (!bOk)
250 {
251 wxLogLastError("CheckMenuItem");
252 }
253 wxMenuItemBase::Check(bCheck);
254 } // end of wxMenuItem::Check
255
256 void wxMenuItem::SetText(
257 const wxString& rText
258 )
259 {
260 //
261 // Don't do anything if label didn't change
262 //
263
264 wxString Text = TextToLabel(rText);
265 if (m_text == Text)
266 return;
267
268 wxMenuItemBase::SetText(Text);
269 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(Text));
270
271 HWND hMenu = GetHMenuOf(m_parentMenu);
272
273 wxCHECK_RET(hMenu, wxT("menuitem without menu"));
274
275 #if wxUSE_ACCEL
276 m_parentMenu->UpdateAccel(this);
277 #endif // wxUSE_ACCEL
278
279 USHORT uId = GetRealId();
280 MENUITEM vItem;
281 USHORT uFlagsOld;
282
283 if (!::WinSendMsg( hMenu
284 ,MM_QUERYITEM
285 ,MPFROM2SHORT(uId, TRUE)
286 ,(MPARAM)&vItem
287 ))
288 {
289 wxLogLastError("GetMenuState");
290 }
291 else
292 {
293 uFlagsOld = vItem.afStyle;
294 if (IsSubMenu())
295 {
296 uFlagsOld |= MIS_SUBMENU;
297 }
298
299 BYTE* pData;
300
301 #if wxUSE_OWNER_DRAWN
302 if (IsOwnerDrawn())
303 {
304 uFlagsOld |= MIS_OWNERDRAW;
305 pData = (BYTE*)this;
306 }
307 else
308 #endif //owner drawn
309 {
310 uFlagsOld |= MIS_TEXT;
311 pData = (BYTE*)Text.c_str();
312 }
313
314 //
315 // Set the style
316 //
317 if (!::WinSendMsg( hMenu
318 ,MM_SETITEM
319 ,MPFROM2SHORT(uId, TRUE)
320 ,(MPARAM)&vItem
321 ))
322 {
323 wxLogLastError(wxT("ModifyMenu"));
324 }
325
326 //
327 // Set the text
328 //
329 if (::WinSendMsg( hMenu
330 ,MM_SETITEMTEXT
331 ,MPFROMSHORT(uId)
332 ,(MPARAM)pData
333 ))
334 {
335 wxLogLastError(wxT("ModifyMenu"));
336 }
337 }
338 } // end of wxMenuItem::SetText
339
340 void wxMenuItem::SetCheckable(
341 bool bCheckable
342 )
343 {
344 wxMenuItemBase::SetCheckable(bCheckable);
345 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable));
346 } // end of wxMenuItem::SetCheckable
347
348 // ----------------------------------------------------------------------------
349 // wxMenuItemBase
350 // ----------------------------------------------------------------------------
351
352 wxMenuItem* wxMenuItemBase::New(
353 wxMenu* pParentMenu
354 , int nId
355 , const wxString& rName
356 , const wxString& rHelp
357 , wxItemKind kind
358 , wxMenu* pSubMenu
359 )
360 {
361 return new wxMenuItem( pParentMenu
362 ,nId
363 ,rName
364 ,rHelp
365 ,kind
366 ,pSubMenu
367 );
368 } // end of wxMenuItemBase::New
369