no message
[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 Init();
126 } // end of wxMenuItem::wxMenuItem
127
128 wxMenuItem::wxMenuItem(
129 wxMenu* pParentMenu
130 , int nId
131 , const wxString& rText
132 , const wxString& rStrHelp
133 , bool bIsCheckable
134 , wxMenu* pSubMenu
135 )
136 : wxMenuItemBase(pParentMenu, nId, rText, rStrHelp, bIsCheckable ? kITEM_CHECK : kITEM_NORMAL, pSubMenu)
137 #if wxUSE_OWNER_DRAWN
138 , wxOwnerDrawn( TextToLabel(rText)
139 ,bCheckable
140 )
141 #endif // owner drawn
142 {
143 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
144
145 Init();
146 } // end of wxMenuItem::wxMenuItem
147
148 void wxMenuItem::Init()
149 {
150 m_radioGroup.start = -1;
151 m_isRadioGroupStart = FALSE;
152
153 #if wxUSE_OWNER_DRAWN
154 // set default menu colors
155 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
156
157 SetTextColour(SYS_COLOR(MENUTEXT));
158 SetBackgroundColour(SYS_COLOR(MENU));
159
160 #undef SYS_COLOR
161
162 // we don't want normal items be owner-drawn
163 ResetOwnerDrawn();
164
165 // tell the owner drawing code to to show the accel string as well
166 SetAccelString(m_text.AfterFirst(_T('\t')));
167 #endif // wxUSE_OWNER_DRAWN
168 }
169
170 wxMenuItem::~wxMenuItem()
171 {
172 } // end of wxMenuItem::~wxMenuItem
173
174 //
175 // Misc
176 // ----
177
178 //
179 // Return the id for calling Win32 API functions
180 //
181 int wxMenuItem::GetRealId() const
182 {
183 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
184 } // end of wxMenuItem::GetRealId
185
186 //
187 // Get item state
188 // --------------
189 bool wxMenuItem::IsChecked() const
190 {
191 USHORT uFlag = SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu)
192 ,MM_QUERYITEMATTR
193 ,MPFROM2SHORT(GetId(), TRUE)
194 ,MPFROMSHORT(MIA_CHECKED)
195 ));
196
197 return (uFlag & MIA_CHECKED);
198 } // end of wxMenuItem::IsChecked
199
200 wxString wxMenuItemBase::GetLabelFromText(
201 const wxString& rText
202 )
203 {
204 wxString label;
205 for ( const wxChar *pc = rText.c_str(); *pc; pc++ )
206 {
207 if ( *pc == wxT('~') || *pc == wxT('&') )
208 {
209 // '~' is the escape character for GTK+ and '&' is the one for
210 // wxWindows - skip both of them
211 continue;
212 }
213
214 label += *pc;
215 }
216 return label;
217 }
218
219 // radio group stuff
220 // -----------------
221
222 void wxMenuItem::SetAsRadioGroupStart()
223 {
224 m_bIsRadioGroupStart = TRUE;
225 } // end of wxMenuItem::SetAsRadioGroupStart
226
227 void wxMenuItem::SetRadioGroupStart(
228 int nStart
229 )
230 {
231 wxASSERT_MSG( !m_bIsRadioGroupStart,
232 _T("should only be called for the next radio items") );
233
234 m_vRadioGroup.m_nStart = nStart;
235 } // end of wxMenuItem::SetRadioGroupStart
236
237 void wxMenuItem::SetRadioGroupEnd(
238 int nEnd
239 )
240 {
241 wxASSERT_MSG( m_bIsRadioGroupStart,
242 _T("should only be called for the first radio item") );
243
244 m_vRadioGroup.m_nEnd = nEnd;
245 } // end of wxMenuItem::SetRadioGroupEnd
246
247 // change item state
248 // -----------------
249
250 void wxMenuItem::Enable(
251 bool bEnable
252 )
253 {
254 bool bOk;
255
256 if (m_isEnabled == bEnable)
257 return;
258 if (bEnable)
259 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
260 ,MM_SETITEMATTR
261 ,MPFROM2SHORT(GetRealId(), TRUE)
262 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
263 );
264 else
265 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
266 ,MM_SETITEMATTR
267 ,MPFROM2SHORT(GetRealId(), TRUE)
268 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
269 );
270 if (!bOk)
271 {
272 wxLogLastError("EnableMenuItem");
273 }
274 wxMenuItemBase::Enable(bEnable);
275 } // end of wxMenuItem::Enable
276
277 void wxMenuItem::Check(
278 bool bCheck
279 )
280 {
281 bool bOk;
282
283 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
284 if (m_isChecked == bCheck)
285 return;
286
287 if (bCheck)
288 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
289 ,MM_SETITEMATTR
290 ,MPFROM2SHORT(GetRealId(), TRUE)
291 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
292 );
293 else
294 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
295 ,MM_SETITEMATTR
296 ,MPFROM2SHORT(GetRealId(), TRUE)
297 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
298 );
299 if (!bOk)
300 {
301 wxLogLastError("CheckMenuItem");
302 }
303 wxMenuItemBase::Check(bCheck);
304 } // end of wxMenuItem::Check
305
306 void wxMenuItem::SetText(
307 const wxString& rText
308 )
309 {
310 //
311 // Don't do anything if label didn't change
312 //
313
314 wxString Text = TextToLabel(rText);
315 if (m_text == Text)
316 return;
317
318 wxMenuItemBase::SetText(Text);
319 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(Text));
320
321 HWND hMenu = GetHMenuOf(m_parentMenu);
322
323 wxCHECK_RET(hMenu, wxT("menuitem without menu"));
324
325 #if wxUSE_ACCEL
326 m_parentMenu->UpdateAccel(this);
327 #endif // wxUSE_ACCEL
328
329 USHORT uId = GetRealId();
330 MENUITEM vItem;
331 USHORT uFlagsOld;
332
333 if (!::WinSendMsg( hMenu
334 ,MM_QUERYITEM
335 ,MPFROM2SHORT(uId, TRUE)
336 ,(MPARAM)&vItem
337 ))
338 {
339 wxLogLastError("GetMenuState");
340 }
341 else
342 {
343 uFlagsOld = vItem.afStyle;
344 if (IsSubMenu())
345 {
346 uFlagsOld |= MIS_SUBMENU;
347 }
348
349 BYTE* pData;
350
351 #if wxUSE_OWNER_DRAWN
352 if (IsOwnerDrawn())
353 {
354 uFlagsOld |= MIS_OWNERDRAW;
355 pData = (BYTE*)this;
356 }
357 else
358 #endif //owner drawn
359 {
360 uFlagsOld |= MIS_TEXT;
361 pData = (BYTE*)Text.c_str();
362 }
363
364 //
365 // Set the style
366 //
367 if (!::WinSendMsg( hMenu
368 ,MM_SETITEM
369 ,MPFROM2SHORT(uId, TRUE)
370 ,(MPARAM)&vItem
371 ))
372 {
373 wxLogLastError(wxT("ModifyMenu"));
374 }
375
376 //
377 // Set the text
378 //
379 if (::WinSendMsg( hMenu
380 ,MM_SETITEMTEXT
381 ,MPFROMSHORT(uId)
382 ,(MPARAM)pData
383 ))
384 {
385 wxLogLastError(wxT("ModifyMenu"));
386 }
387 }
388 } // end of wxMenuItem::SetText
389
390 void wxMenuItem::SetCheckable(
391 bool bCheckable
392 )
393 {
394 wxMenuItemBase::SetCheckable(bCheckable);
395 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable));
396 } // end of wxMenuItem::SetCheckable
397
398 // ----------------------------------------------------------------------------
399 // wxMenuItemBase
400 // ----------------------------------------------------------------------------
401
402 wxMenuItem* wxMenuItemBase::New(
403 wxMenu* pParentMenu
404 , int nId
405 , const wxString& rName
406 , const wxString& rHelp
407 , wxItemKind kind
408 , wxMenu* pSubMenu
409 )
410 {
411 return new wxMenuItem( pParentMenu
412 ,nId
413 ,rName
414 ,rHelp
415 ,kind
416 ,pSubMenu
417 );
418 } // end of wxMenuItemBase::New
419