Fixes for OS/2 wxUniv merge.
[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; *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 if (*pc == wxT('/'))
78 // {
79 // Title << wxT('\\');
80 // }
81 else
82 {
83 if ( *pc == wxT('~') )
84 {
85 // tildes must be doubled to prevent them from being
86 // interpreted as accelerator character prefix by PM ???
87 Title << *pc;
88 }
89 Title << *pc;
90 }
91 }
92 return Title;
93 }
94
95 // ============================================================================
96 // implementation
97 // ============================================================================
98
99 // ----------------------------------------------------------------------------
100 // dynamic classes implementation
101 // ----------------------------------------------------------------------------
102
103 #if wxUSE_OWNER_DRAWN
104 IMPLEMENT_DYNAMIC_CLASS2(wxMenuItem, wxMenuItemBase, wxOwnerDrawn)
105 #else //!USE_OWNER_DRAWN
106 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxMenuItemBase)
107 #endif //USE_OWNER_DRAWN
108
109 // ----------------------------------------------------------------------------
110 // wxMenuItem
111 // ----------------------------------------------------------------------------
112
113 // ctor & dtor
114 // -----------
115
116 wxMenuItem::wxMenuItem(
117 wxMenu* pParentMenu
118 , int nId
119 , const wxString& rText
120 , const wxString& rStrHelp
121 , bool bCheckable
122 , wxMenu* pSubMenu
123 )
124 #if wxUSE_OWNER_DRAWN
125 : wxOwnerDrawn( TextToLabel(rText)
126 ,bCheckable
127 )
128 #endif // owner drawn
129 {
130 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
131
132 #if wxUSE_OWNER_DRAWN
133
134 //
135 // Set default menu colors
136 //
137 #define SYS_COLOR(c) (wxSystemSettings::GetSystemColour(wxSYS_COLOUR_##c))
138
139 SetTextColour(SYS_COLOR(MENUTEXT));
140 SetBackgroundColour(SYS_COLOR(MENU));
141
142 //
143 // We don't want normal items be owner-drawn
144 //
145 ResetOwnerDrawn();
146
147 #undef SYS_COLOR
148 #endif // wxUSE_OWNER_DRAWN
149
150 m_parentMenu = pParentMenu;
151 m_subMenu = pSubMenu;
152 m_isEnabled = TRUE;
153 m_isChecked = FALSE;
154 m_id = nId;
155 m_text = TextToLabel(rText);
156 m_isCheckable = bCheckable;
157 m_help = rStrHelp;
158 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
159 m_vMenuData.id= nId;
160 } // end of wxMenuItem::wxMenuItem
161
162 wxMenuItem::~wxMenuItem()
163 {
164 } // end of wxMenuItem::~wxMenuItem
165
166 //
167 // Misc
168 // ----
169
170 //
171 // Return the id for calling Win32 API functions
172 //
173 int wxMenuItem::GetRealId() const
174 {
175 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
176 } // end of wxMenuItem::GetRealId
177
178 //
179 // Get item state
180 // --------------
181 bool wxMenuItem::IsChecked() const
182 {
183 USHORT uFlag = SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu)
184 ,MM_QUERYITEMATTR
185 ,MPFROM2SHORT(GetId(), TRUE)
186 ,MPFROMSHORT(MIA_CHECKED)
187 ));
188
189 return (uFlag & MIA_CHECKED);
190 } // end of wxMenuItem::IsChecked
191
192 wxString wxMenuItemBase::GetLabelFromText(
193 const wxString& rText
194 )
195 {
196 wxString label;
197 for ( const wxChar *pc = rText.c_str(); *pc; pc++ )
198 {
199 if ( *pc == wxT('~') || *pc == wxT('&') )
200 {
201 // '~' is the escape character for GTK+ and '&' is the one for
202 // wxWindows - skip both of them
203 continue;
204 }
205
206 label += *pc;
207 }
208 return label;
209 }
210
211 // change item state
212 // -----------------
213
214 void wxMenuItem::Enable(
215 bool bEnable
216 )
217 {
218 bool bOk;
219
220 if (m_isEnabled == bEnable)
221 return;
222 if (bEnable)
223 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
224 ,MM_SETITEMATTR
225 ,MPFROM2SHORT(GetRealId(), TRUE)
226 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
227 );
228 else
229 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
230 ,MM_SETITEMATTR
231 ,MPFROM2SHORT(GetRealId(), TRUE)
232 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
233 );
234 if (!bOk)
235 {
236 wxLogLastError("EnableMenuItem");
237 }
238 wxMenuItemBase::Enable(bEnable);
239 } // end of wxMenuItem::Enable
240
241 void wxMenuItem::Check(
242 bool bCheck
243 )
244 {
245 bool bOk;
246
247 wxCHECK_RET( m_isCheckable, wxT("only checkable items may be checked") );
248 if (m_isChecked == bCheck)
249 return;
250 if (bCheck)
251 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
252 ,MM_SETITEMATTR
253 ,MPFROM2SHORT(GetRealId(), TRUE)
254 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
255 );
256 else
257 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
258 ,MM_SETITEMATTR
259 ,MPFROM2SHORT(GetRealId(), TRUE)
260 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
261 );
262 if (!bOk)
263 {
264 wxLogLastError("CheckMenuItem");
265 }
266 wxMenuItemBase::Check(bCheck);
267 } // end of wxMenuItem::Check
268
269 void wxMenuItem::SetText(
270 const wxString& rText
271 )
272 {
273 //
274 // Don't do anything if label didn't change
275 //
276
277 wxString Text = TextToLabel(rText);
278 if (m_text == Text)
279 return;
280
281 wxMenuItemBase::SetText(Text);
282 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(Text));
283
284 HWND hMenu = GetHMenuOf(m_parentMenu);
285
286 wxCHECK_RET(hMenu, wxT("menuitem without menu"));
287
288 #if wxUSE_ACCEL
289 m_parentMenu->UpdateAccel(this);
290 #endif // wxUSE_ACCEL
291
292 USHORT uId = GetRealId();
293 MENUITEM vItem;
294 USHORT uFlagsOld;
295
296 if (!::WinSendMsg( hMenu
297 ,MM_QUERYITEM
298 ,MPFROM2SHORT(uId, TRUE)
299 ,(MPARAM)&vItem
300 ))
301 {
302 wxLogLastError("GetMenuState");
303 }
304 else
305 {
306 uFlagsOld = vItem.afStyle;
307 if (IsSubMenu())
308 {
309 uFlagsOld |= MIS_SUBMENU;
310 }
311
312 BYTE* pData;
313
314 #if wxUSE_OWNER_DRAWN
315 if (IsOwnerDrawn())
316 {
317 uFlagsOld |= MIS_OWNERDRAW;
318 pData = (BYTE*)this;
319 }
320 else
321 #endif //owner drawn
322 {
323 uFlagsOld |= MIS_TEXT;
324 pData = (BYTE*)Text.c_str();
325 }
326
327 //
328 // Set the style
329 //
330 if (!::WinSendMsg( hMenu
331 ,MM_SETITEM
332 ,MPFROM2SHORT(uId, TRUE)
333 ,(MPARAM)&vItem
334 ))
335 {
336 wxLogLastError(wxT("ModifyMenu"));
337 }
338
339 //
340 // Set the text
341 //
342 if (::WinSendMsg( hMenu
343 ,MM_SETITEMTEXT
344 ,MPFROMSHORT(uId)
345 ,(MPARAM)pData
346 ))
347 {
348 wxLogLastError(wxT("ModifyMenu"));
349 }
350 }
351 } // end of wxMenuItem::SetText
352
353 void wxMenuItem::SetCheckable(
354 bool bCheckable
355 )
356 {
357 wxMenuItemBase::SetCheckable(bCheckable);
358 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable));
359 } // end of wxMenuItem::SetCheckable
360
361 // ----------------------------------------------------------------------------
362 // wxMenuItemBase
363 // ----------------------------------------------------------------------------
364
365 wxMenuItem* wxMenuItemBase::New(
366 wxMenu* pParentMenu
367 , int nId
368 , const wxString& rName
369 , const wxString& rHelp
370 , bool bIsCheckable
371 , wxMenu* pSubMenu
372 )
373 {
374 return new wxMenuItem( pParentMenu
375 ,nId
376 ,rName
377 ,rHelp
378 ,bIsCheckable
379 ,pSubMenu
380 );
381 } // end of wxMenuItemBase::New
382