]> git.saurik.com Git - wxWidgets.git/blame - src/os2/menuitem.cpp
Empty string corrections.
[wxWidgets.git] / src / os2 / menuitem.cpp
CommitLineData
0e320a79
DW
1///////////////////////////////////////////////////////////////////////////////
2// Name: menuitem.cpp
3// Purpose: wxMenuItem implementation
75f11ad7
DW
4// Author: David Webster
5// Modified by:
6// Created: 10/10/98
0e320a79 7// RCS-ID: $Id$
75f11ad7 8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
0e320a79
DW
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// headers & declarations
14// ============================================================================
15
7a0d28d8
SN
16#ifdef __GNUG__
17 #pragma implementation "menuitem.h"
18#endif
19
75f11ad7
DW
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
0e320a79 34#include "wx/menuitem.h"
75f11ad7
DW
35#include "wx/log.h"
36
c5fb56c0
DW
37#if wxUSE_ACCEL
38 #include "wx/accel.h"
39#endif // wxUSE_ACCEL
40
75f11ad7
DW
41#include "wx/os2/private.h"
42
43// ---------------------------------------------------------------------------
c5fb56c0 44// macro
75f11ad7
DW
45// ---------------------------------------------------------------------------
46
c5fb56c0 47// hide the ugly cast
75f11ad7 48#define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
0e320a79 49
c5fb56c0
DW
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
0e320a79
DW
57// ============================================================================
58// implementation
59// ============================================================================
60
61// ----------------------------------------------------------------------------
62// dynamic classes implementation
63// ----------------------------------------------------------------------------
64
4a46a5df 65IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
0e320a79
DW
66
67// ----------------------------------------------------------------------------
68// wxMenuItem
69// ----------------------------------------------------------------------------
70
71// ctor & dtor
72// -----------
73
22e90769
DW
74wxMenuItem::wxMenuItem(
75 wxMenu* pParentMenu
76, int nId
ab4fece8
DW
77, const wxString& rsText
78, const wxString& rsHelp
79, wxItemKind eKind
22e90769
DW
80, wxMenu* pSubMenu
81)
ab4fece8
DW
82: wxMenuItemBase( pParentMenu
83 ,nId
3a7c1253 84 ,wxPMTextToLabel(rsText)
ab4fece8
DW
85 ,rsHelp
86 ,eKind
87 ,pSubMenu
88 )
75f11ad7 89#if wxUSE_OWNER_DRAWN
3a7c1253 90, wxOwnerDrawn( wxPMTextToLabel(rsText)
ab4fece8 91 ,eKind == wxITEM_CHECK
22e90769 92 )
c5fb56c0 93#endif // owner drawn
0e320a79 94{
22e90769 95 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
8635b0db
DW
96 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
97 m_vMenuData.id = (USHORT)nId;
75f11ad7 98
f95255e2
DW
99 Init();
100} // end of wxMenuItem::wxMenuItem
101
102wxMenuItem::wxMenuItem(
103 wxMenu* pParentMenu
104, int nId
ab4fece8
DW
105, const wxString& rsText
106, const wxString& rsHelp
f95255e2
DW
107, bool bIsCheckable
108, wxMenu* pSubMenu
109)
ab4fece8
DW
110: wxMenuItemBase( pParentMenu
111 ,nId
3a7c1253 112 ,wxPMTextToLabel(rsText)
ab4fece8
DW
113 ,rsHelp
114 ,bIsCheckable ? wxITEM_CHECK : wxITEM_NORMAL
115 ,pSubMenu
116 )
f95255e2 117#if wxUSE_OWNER_DRAWN
3a7c1253 118, wxOwnerDrawn( wxPMTextToLabel(rsText)
ab4fece8 119 ,bIsCheckable
f95255e2
DW
120 )
121#endif // owner drawn
122{
123 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
938aa9c4
DW
124 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
125 m_vMenuData.id = (USHORT)nId;
f95255e2
DW
126
127 Init();
128} // end of wxMenuItem::wxMenuItem
129
130void wxMenuItem::Init()
131{
ab4fece8
DW
132 m_vRadioGroup.m_nStart = -1;
133 m_bIsRadioGroupStart = FALSE;
22e90769 134
f95255e2 135#if wxUSE_OWNER_DRAWN
ab4fece8
DW
136 //
137 // Set default menu colors
138 //
a756f210 139 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
75f11ad7
DW
140
141 SetTextColour(SYS_COLOR(MENUTEXT));
142 SetBackgroundColour(SYS_COLOR(MENU));
143
ab4fece8
DW
144 //
145 // We don't want normal items be owner-drawn
146 //
f95255e2 147 ResetOwnerDrawn();
c9667cda 148 #undef SYS_COLOR
d65c269b 149
ab4fece8
DW
150 //
151 // Tell the owner drawing code to to show the accel string as well
152 //
f95255e2
DW
153 SetAccelString(m_text.AfterFirst(_T('\t')));
154#endif // wxUSE_OWNER_DRAWN
ab4fece8 155} // end of wxMenuItem::Init
0e320a79 156
75f11ad7 157wxMenuItem::~wxMenuItem()
0e320a79 158{
22e90769 159} // end of wxMenuItem::~wxMenuItem
0e320a79 160
22e90769
DW
161//
162// Misc
0e320a79
DW
163// ----
164
22e90769
DW
165//
166// Return the id for calling Win32 API functions
167//
75f11ad7
DW
168int wxMenuItem::GetRealId() const
169{
c5fb56c0 170 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
22e90769 171} // end of wxMenuItem::GetRealId
c5fb56c0 172
22e90769
DW
173//
174// Get item state
c5fb56c0 175// --------------
c5fb56c0
DW
176bool wxMenuItem::IsChecked() const
177{
6670f564
WS
178 USHORT uFlag = SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu)
179 ,MM_QUERYITEMATTR
180 ,MPFROM2SHORT(GetId(), TRUE)
181 ,MPFROMSHORT(MIA_CHECKED)
182 ));
22e90769 183
6670f564 184 return (uFlag & MIA_CHECKED) == MIA_CHECKED ;
22e90769
DW
185} // end of wxMenuItem::IsChecked
186
187wxString wxMenuItemBase::GetLabelFromText(
c9667cda 188 const wxString& rsText
22e90769 189)
c5fb56c0 190{
c9667cda
DW
191 wxString sLabel;
192
0fba44b4 193 for (const wxChar* zPc = rsText.c_str(); *zPc; zPc++)
2b33b728 194 {
c9667cda 195 if (*zPc == wxT('~') || *zPc == wxT('&'))
2b33b728 196 {
c9667cda
DW
197 //
198 // '~' is the escape character for OS/2PM and '&' is the one for
77ffb593 199 // wxWidgets - skip both of them
c9667cda 200 //
2b33b728
SN
201 continue;
202 }
c9667cda 203 sLabel += *zPc;
2b33b728 204 }
c9667cda
DW
205 return sLabel;
206} // end of wxMenuItemBase::GetLabelFromText
75f11ad7 207
598d8cac
DW
208//
209// Radio group stuff
f95255e2 210// -----------------
598d8cac 211//
f95255e2
DW
212void wxMenuItem::SetAsRadioGroupStart()
213{
6670f564 214 m_bIsRadioGroupStart = true;
f95255e2
DW
215} // end of wxMenuItem::SetAsRadioGroupStart
216
217void wxMenuItem::SetRadioGroupStart(
218 int nStart
219)
220{
598d8cac
DW
221 wxASSERT_MSG( !m_bIsRadioGroupStart
222 ,_T("should only be called for the next radio items")
223 );
f95255e2
DW
224
225 m_vRadioGroup.m_nStart = nStart;
598d8cac 226} // wxMenuItem::SetRadioGroupStart
f95255e2
DW
227
228void wxMenuItem::SetRadioGroupEnd(
229 int nEnd
230)
231{
598d8cac
DW
232 wxASSERT_MSG( m_bIsRadioGroupStart
233 ,_T("should only be called for the first radio item")
234 );
f95255e2
DW
235 m_vRadioGroup.m_nEnd = nEnd;
236} // end of wxMenuItem::SetRadioGroupEnd
237
0e320a79
DW
238// change item state
239// -----------------
240
22e90769
DW
241void wxMenuItem::Enable(
242 bool bEnable
243)
0e320a79 244{
22e90769 245 bool bOk;
75f11ad7 246
22e90769
DW
247 if (m_isEnabled == bEnable)
248 return;
249 if (bEnable)
914589c2
DW
250 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
251 ,MM_SETITEMATTR
252 ,MPFROM2SHORT(GetRealId(), TRUE)
f6bcfd97 253 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
914589c2 254 );
22e90769 255 else
914589c2
DW
256 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
257 ,MM_SETITEMATTR
258 ,MPFROM2SHORT(GetRealId(), TRUE)
f6bcfd97 259 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
914589c2 260 );
22e90769
DW
261 if (!bOk)
262 {
2173b18f 263 wxLogLastError(wxT("EnableMenuItem"));
0e320a79 264 }
22e90769
DW
265 wxMenuItemBase::Enable(bEnable);
266} // end of wxMenuItem::Enable
0e320a79 267
22e90769
DW
268void wxMenuItem::Check(
269 bool bCheck
270)
0e320a79 271{
22e90769 272 bool bOk;
75f11ad7 273
d65c269b 274 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
22e90769 275 if (m_isChecked == bCheck)
c5fb56c0 276 return;
f95255e2 277
50b39f8f 278 HMENU hMenu = GetHmenuOf(m_parentMenu);
598d8cac
DW
279
280 if (GetKind() == wxITEM_RADIO)
ab4fece8
DW
281 {
282 //
283 // It doesn't make sense to uncheck a radio item - what would this do?
284 //
285 if (!bCheck)
286 return;
287
288 //
289 // Get the index of this item in the menu
290 //
291 const wxMenuItemList& rItems = m_parentMenu->GetMenuItems();
292 int nPos = rItems.IndexOf(this);
ab4fece8 293
598d8cac
DW
294 wxCHECK_RET( nPos != wxNOT_FOUND
295 ,_T("menuitem not found in the menu items list?")
296 );
ab4fece8
DW
297
298 //
299 // Get the radio group range
300 //
598d8cac
DW
301 int nStart;
302 int nEnd;
ab4fece8
DW
303
304 if (m_bIsRadioGroupStart)
305 {
598d8cac
DW
306 //
307 // We already have all information we need
308 //
ab4fece8 309 nStart = nPos;
598d8cac 310 nEnd = m_vRadioGroup.m_nEnd;
ab4fece8 311 }
598d8cac 312 else // next radio group item
ab4fece8
DW
313 {
314 //
315 // Get the radio group end from the start item
316 //
317 nStart = m_vRadioGroup.m_nStart;
318 nEnd = rItems.Item(nStart)->GetData()->m_vRadioGroup.m_nEnd;
319 }
320
321 //
322 // Also uncheck all the other items in this radio group
323 //
2461cfa0 324 wxMenuItemList::compatibility_iterator node = rItems.Item(nStart);
ab4fece8 325
2461cfa0 326 for (int n = nStart; n <= nEnd && node; n++)
ab4fece8 327 {
ab4fece8
DW
328 if (n == nPos)
329 {
598d8cac
DW
330 ::WinSendMsg( hMenu
331 ,MM_SETITEMATTR
332 ,MPFROM2SHORT(n, TRUE)
333 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
334 );
ab4fece8 335 }
598d8cac 336 if (n != nPos)
ab4fece8 337 {
2461cfa0 338 node->GetData()->m_isChecked = FALSE;
598d8cac
DW
339 ::WinSendMsg( hMenu
340 ,MM_SETITEMATTR
341 ,MPFROM2SHORT(n, TRUE)
342 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
343 );
ab4fece8 344 }
2461cfa0 345 node = node->GetNext();
ab4fece8
DW
346 }
347 }
348 else // check item
349 {
350 if (bCheck)
50b39f8f 351 bOk = (bool)::WinSendMsg( hMenu
ab4fece8
DW
352 ,MM_SETITEMATTR
353 ,MPFROM2SHORT(GetRealId(), TRUE)
354 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
355 );
356 else
50b39f8f 357 bOk = (bool)::WinSendMsg( hMenu
ab4fece8
DW
358 ,MM_SETITEMATTR
359 ,MPFROM2SHORT(GetRealId(), TRUE)
360 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
361 );
362 }
22e90769
DW
363 if (!bOk)
364 {
2173b18f 365 wxLogLastError(wxT("CheckMenuItem"));
75f11ad7 366 }
22e90769
DW
367 wxMenuItemBase::Check(bCheck);
368} // end of wxMenuItem::Check
75f11ad7 369
6670f564 370void wxMenuItem::SetText( const wxString& rText )
75f11ad7 371{
22e90769
DW
372 //
373 // Don't do anything if label didn't change
374 //
2b33b728 375
3a7c1253 376 wxString sText = wxPMTextToLabel(rText);
50b39f8f 377 if (m_text == sText)
75f11ad7
DW
378 return;
379
50b39f8f
DW
380 wxMenuItemBase::SetText(sText);
381 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText));
57ff8a87
DW
382#if wxUSE_OWNER_DRAWN
383 SetAccelString(rText.AfterFirst(_T('\t')));
384#endif // wxUSE_OWNER_DRAWN
22e90769 385
50b39f8f 386 HWND hMenu = GetHmenuOf(m_parentMenu);
22e90769
DW
387
388 wxCHECK_RET(hMenu, wxT("menuitem without menu"));
75f11ad7 389
c5fb56c0
DW
390#if wxUSE_ACCEL
391 m_parentMenu->UpdateAccel(this);
392#endif // wxUSE_ACCEL
75f11ad7 393
6670f564
WS
394 USHORT uId = (USHORT)GetRealId();
395 MENUITEM vItem;
396 USHORT uFlagsOld;
914589c2 397
22e90769
DW
398 if (!::WinSendMsg( hMenu
399 ,MM_QUERYITEM
400 ,MPFROM2SHORT(uId, TRUE)
401 ,(MPARAM)&vItem
402 ))
75f11ad7 403 {
2173b18f 404 wxLogLastError(wxT("GetMenuState"));
75f11ad7
DW
405 }
406 else
407 {
22e90769
DW
408 uFlagsOld = vItem.afStyle;
409 if (IsSubMenu())
75f11ad7 410 {
22e90769 411 uFlagsOld |= MIS_SUBMENU;
75f11ad7
DW
412 }
413
22e90769 414 BYTE* pData;
c5fb56c0 415
75f11ad7 416#if wxUSE_OWNER_DRAWN
22e90769 417 if (IsOwnerDrawn())
75f11ad7 418 {
22e90769
DW
419 uFlagsOld |= MIS_OWNERDRAW;
420 pData = (BYTE*)this;
75f11ad7
DW
421 }
422 else
423#endif //owner drawn
424 {
22e90769 425 uFlagsOld |= MIS_TEXT;
50b39f8f 426 pData = (BYTE*)sText.c_str();
22e90769
DW
427 }
428
429 //
430 // Set the style
431 //
432 if (!::WinSendMsg( hMenu
433 ,MM_SETITEM
434 ,MPFROM2SHORT(uId, TRUE)
435 ,(MPARAM)&vItem
436 ))
437 {
438 wxLogLastError(wxT("ModifyMenu"));
75f11ad7
DW
439 }
440
22e90769
DW
441 //
442 // Set the text
443 //
444 if (::WinSendMsg( hMenu
445 ,MM_SETITEMTEXT
446 ,MPFROMSHORT(uId)
447 ,(MPARAM)pData
448 ))
75f11ad7
DW
449 {
450 wxLogLastError(wxT("ModifyMenu"));
451 }
452 }
22e90769 453} // end of wxMenuItem::SetText
0e320a79 454
22e90769
DW
455void wxMenuItem::SetCheckable(
456 bool bCheckable
457)
c5fb56c0 458{
22e90769
DW
459 wxMenuItemBase::SetCheckable(bCheckable);
460 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable));
461} // end of wxMenuItem::SetCheckable
c5fb56c0
DW
462
463// ----------------------------------------------------------------------------
464// wxMenuItemBase
465// ----------------------------------------------------------------------------
466
22e90769
DW
467wxMenuItem* wxMenuItemBase::New(
468 wxMenu* pParentMenu
469, int nId
470, const wxString& rName
471, const wxString& rHelp
d65c269b 472, wxItemKind kind
22e90769
DW
473, wxMenu* pSubMenu
474)
c5fb56c0 475{
22e90769
DW
476 return new wxMenuItem( pParentMenu
477 ,nId
478 ,rName
479 ,rHelp
d65c269b 480 ,kind
22e90769
DW
481 ,pSubMenu
482 );
483} // end of wxMenuItemBase::New